Merge branch 'dev' of https://github.com/Regalis11/Barotrauma.git into unstable-tests
This commit is contained in:
@@ -13,7 +13,7 @@ namespace Barotrauma
|
||||
private float? defaultZoom;
|
||||
public float DefaultZoom
|
||||
{
|
||||
get { return defaultZoom ?? (GameMain.Config == null || GameMain.Config.EnableMouseLook ? 1.3f : 1.0f); }
|
||||
get { return defaultZoom ?? (GameSettings.CurrentConfig.EnableMouseLook ? 1.3f : 1.0f); }
|
||||
set
|
||||
{
|
||||
defaultZoom = MathHelper.Clamp(value, 0.5f, 2.0f);
|
||||
@@ -269,10 +269,10 @@ namespace Barotrauma
|
||||
if (PlayerInput.KeyDown(Keys.LeftShift)) { moveSpeed *= 2.0f; }
|
||||
if (PlayerInput.KeyDown(Keys.LeftControl)) { moveSpeed *= 0.5f; }
|
||||
|
||||
if (GameMain.Config.KeyBind(InputType.Left).IsDown()) { moveInput.X -= 1.0f; }
|
||||
if (GameMain.Config.KeyBind(InputType.Right).IsDown()) { moveInput.X += 1.0f; }
|
||||
if (GameMain.Config.KeyBind(InputType.Down).IsDown()) { moveInput.Y -= 1.0f; }
|
||||
if (GameMain.Config.KeyBind(InputType.Up).IsDown()) { moveInput.Y += 1.0f; }
|
||||
if (GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Left].IsDown()) { moveInput.X -= 1.0f; }
|
||||
if (GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Right].IsDown()) { moveInput.X += 1.0f; }
|
||||
if (GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Down].IsDown()) { moveInput.Y -= 1.0f; }
|
||||
if (GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Up].IsDown()) { moveInput.Y += 1.0f; }
|
||||
}
|
||||
|
||||
velocity = Vector2.Lerp(velocity, moveInput, deltaTime * 10.0f);
|
||||
@@ -346,7 +346,7 @@ namespace Barotrauma
|
||||
float scaledZoom = MathHelper.Lerp(DefaultZoom, MinZoom, zoomOutAmount) * globalZoomScale;
|
||||
//zoom in further if zoomOutAmount is low and resolution is lower than reference
|
||||
float newZoom = scaledZoom * (MathHelper.Lerp(0.3f * (1f - Math.Min(globalZoomScale, 1f)), 0f,
|
||||
(GameMain.Config == null || GameMain.Config.EnableMouseLook) ? (float)Math.Sqrt(offsetUnscaledLen) : 0.3f) + 1f);
|
||||
(GameSettings.CurrentConfig.EnableMouseLook) ? (float)Math.Sqrt(offsetUnscaledLen) : 0.3f) + 1f);
|
||||
|
||||
Zoom += (newZoom - zoom) / ZoomSmoothness;
|
||||
}
|
||||
|
||||
@@ -37,8 +37,9 @@ namespace Barotrauma
|
||||
targetPos = attackWorldPos;
|
||||
}
|
||||
targetPos.Y = -targetPos.Y;
|
||||
GUI.DrawLine(spriteBatch, pos, targetPos, GUI.Style.Red * 0.5f, 0, 4);
|
||||
if (wallTarget != null)
|
||||
|
||||
GUI.DrawLine(spriteBatch, pos, targetPos, GUIStyle.Red * 0.5f, 0, 4);
|
||||
if (wallTarget != null && !IsCoolDownRunning)
|
||||
{
|
||||
Vector2 wallTargetPos = wallTarget.Position;
|
||||
if (wallTarget.Structure.Submarine != null) { wallTargetPos += wallTarget.Structure.Submarine.Position; }
|
||||
@@ -46,19 +47,19 @@ namespace Barotrauma
|
||||
GUI.DrawRectangle(spriteBatch, wallTargetPos - new Vector2(10.0f, 10.0f), new Vector2(20.0f, 20.0f), Color.Orange, false);
|
||||
GUI.DrawLine(spriteBatch, pos, wallTargetPos, Color.Orange * 0.5f, 0, 5);
|
||||
}
|
||||
GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 60.0f, $"{SelectedAiTarget.Entity} ({GetTargetMemory(SelectedAiTarget, false)?.Priority.FormatZeroDecimal()})", GUI.Style.Red, Color.Black);
|
||||
GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 40.0f, $"({targetValue.FormatZeroDecimal()})", GUI.Style.Red, Color.Black);
|
||||
GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 60.0f, $"{SelectedAiTarget.Entity} ({GetTargetMemory(SelectedAiTarget, false)?.Priority.FormatZeroDecimal()})", GUIStyle.Red, Color.Black);
|
||||
GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 40.0f, $"({targetValue.FormatZeroDecimal()})", GUIStyle.Red, Color.Black);
|
||||
}
|
||||
|
||||
/*GUI.Font.DrawString(spriteBatch, targetValue.ToString(), pos - Vector2.UnitY * 80.0f, GUI.Style.Red);
|
||||
GUI.Font.DrawString(spriteBatch, "updatetargets: " + MathUtils.Round(updateTargetsTimer, 0.1f), pos - Vector2.UnitY * 100.0f, GUI.Style.Red);
|
||||
GUI.Font.DrawString(spriteBatch, "cooldown: " + MathUtils.Round(coolDownTimer, 0.1f), pos - Vector2.UnitY * 120.0f, GUI.Style.Red);*/
|
||||
/*GUIStyle.Font.DrawString(spriteBatch, targetValue.ToString(), pos - Vector2.UnitY * 80.0f, GUIStyle.Red);
|
||||
GUIStyle.Font.DrawString(spriteBatch, "updatetargets: " + MathUtils.Round(updateTargetsTimer, 0.1f), pos - Vector2.UnitY * 100.0f, GUIStyle.Red);
|
||||
GUIStyle.Font.DrawString(spriteBatch, "cooldown: " + MathUtils.Round(coolDownTimer, 0.1f), pos - Vector2.UnitY * 120.0f, GUIStyle.Red);*/
|
||||
|
||||
Color stateColor = Color.White;
|
||||
switch (State)
|
||||
{
|
||||
case AIState.Attack:
|
||||
stateColor = IsCoolDownRunning ? Color.Orange : GUI.Style.Red;
|
||||
stateColor = IsCoolDownRunning ? Color.Orange : GUIStyle.Red;
|
||||
break;
|
||||
case AIState.Escape:
|
||||
stateColor = Color.LightBlue;
|
||||
@@ -78,13 +79,13 @@ namespace Barotrauma
|
||||
{
|
||||
GUI.DrawLine(spriteBatch,
|
||||
ConvertUnits.ToDisplayUnits(new Vector2(attachJoint.WorldAnchorA.X, -attachJoint.WorldAnchorA.Y)),
|
||||
ConvertUnits.ToDisplayUnits(new Vector2(attachJoint.WorldAnchorB.X, -attachJoint.WorldAnchorB.Y)), GUI.Style.Green, 0, 4);
|
||||
ConvertUnits.ToDisplayUnits(new Vector2(attachJoint.WorldAnchorB.X, -attachJoint.WorldAnchorB.Y)), GUIStyle.Green, 0, 4);
|
||||
}
|
||||
|
||||
if (LatchOntoAI.AttachPos.HasValue)
|
||||
{
|
||||
GUI.DrawLine(spriteBatch, pos,
|
||||
ConvertUnits.ToDisplayUnits(new Vector2(LatchOntoAI.AttachPos.Value.X, -LatchOntoAI.AttachPos.Value.Y)), GUI.Style.Green, 0, 3);
|
||||
ConvertUnits.ToDisplayUnits(new Vector2(LatchOntoAI.AttachPos.Value.X, -LatchOntoAI.AttachPos.Value.Y)), GUIStyle.Green, 0, 3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,12 +109,12 @@ namespace Barotrauma
|
||||
GUI.DrawLine(spriteBatch,
|
||||
new Vector2(currentNode.DrawPosition.X, -currentNode.DrawPosition.Y),
|
||||
new Vector2(previousNode.DrawPosition.X, -previousNode.DrawPosition.Y),
|
||||
GUI.Style.Red * 0.5f, 0, 3);
|
||||
GUIStyle.Red * 0.5f, 0, 3);
|
||||
|
||||
GUI.SmallFont.DrawString(spriteBatch,
|
||||
GUIStyle.SmallFont.DrawString(spriteBatch,
|
||||
currentNode.ID.ToString(),
|
||||
new Vector2(currentNode.DrawPosition.X - 10, -currentNode.DrawPosition.Y - 30),
|
||||
GUI.Style.Red);
|
||||
GUIStyle.Red);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,7 +125,7 @@ namespace Barotrauma
|
||||
Vector2 hitPos = ConvertUnits.ToDisplayUnits(steeringManager.AvoidRayCastHitPosition);
|
||||
hitPos.Y = -hitPos.Y;
|
||||
|
||||
GUI.DrawLine(spriteBatch, hitPos, hitPos + new Vector2(steeringManager.AvoidDir.X, -steeringManager.AvoidDir.Y) * 100, GUI.Style.Red, width: 5);
|
||||
GUI.DrawLine(spriteBatch, hitPos, hitPos + new Vector2(steeringManager.AvoidDir.X, -steeringManager.AvoidDir.Y) * 100, GUIStyle.Red, width: 5);
|
||||
//GUI.DrawLine(spriteBatch, pos, ConvertUnits.ToDisplayUnits(steeringManager.AvoidLookAheadPos.X, -steeringManager.AvoidLookAheadPos.Y), Color.Orange, width: 4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Barotrauma
|
||||
|
||||
if (SelectedAiTarget?.Entity != null)
|
||||
{
|
||||
//GUI.DrawLine(spriteBatch, pos, new Vector2(SelectedAiTarget.WorldPosition.X, -SelectedAiTarget.WorldPosition.Y), GUI.Style.Red);
|
||||
//GUI.DrawLine(spriteBatch, pos, new Vector2(SelectedAiTarget.WorldPosition.X, -SelectedAiTarget.WorldPosition.Y), GUIStyle.Red);
|
||||
//GUI.DrawString(spriteBatch, pos + textOffset, $"AI TARGET: {SelectedAiTarget.Entity.ToString()}", Color.White, Color.Black);
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace Barotrauma
|
||||
new Vector2(previousNode.DrawPosition.X, -previousNode.DrawPosition.Y),
|
||||
Color.Blue * 0.5f, 0, 3);
|
||||
|
||||
GUI.SmallFont.DrawString(spriteBatch,
|
||||
GUIStyle.SmallFont.DrawString(spriteBatch,
|
||||
currentNode.ID.ToString(),
|
||||
new Vector2(currentNode.DrawPosition.X - 10, -currentNode.DrawPosition.Y - 30),
|
||||
Color.Blue);
|
||||
|
||||
@@ -6,16 +6,16 @@ namespace Barotrauma
|
||||
{
|
||||
public static Color ObjectiveIconColor => Color.LightGray;
|
||||
|
||||
public static Sprite GetSprite(string identifier, string option, Entity targetEntity)
|
||||
public static Sprite GetSprite(Identifier identifier, Identifier option, Entity targetEntity)
|
||||
{
|
||||
if (string.IsNullOrEmpty(identifier))
|
||||
if (identifier == Identifier.Empty)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
identifier = identifier.RemoveWhitespace();
|
||||
if (Order.Prefabs.TryGetValue(identifier, out Order orderPrefab))
|
||||
if (OrderPrefab.Prefabs.ContainsKey(identifier))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(option) && orderPrefab.OptionSprites.TryGetValue(option, out var optionSprite))
|
||||
OrderPrefab orderPrefab = OrderPrefab.Prefabs[identifier];
|
||||
if (option != Identifier.Empty && orderPrefab.OptionSprites.TryGetValue(option, out var optionSprite))
|
||||
{
|
||||
return optionSprite;
|
||||
}
|
||||
@@ -25,7 +25,7 @@ namespace Barotrauma
|
||||
}
|
||||
return orderPrefab.SymbolSprite;
|
||||
}
|
||||
return GUI.Style.GetComponentStyle($"{identifier}objectiveicon")?.GetDefaultSprite();
|
||||
return GUIStyle.GetComponentStyle($"{identifier}objectiveicon")?.GetDefaultSprite();
|
||||
}
|
||||
|
||||
public Sprite GetSprite()
|
||||
|
||||
@@ -28,13 +28,13 @@ namespace Barotrauma
|
||||
{
|
||||
if (item.Prefab.BrokenSprites.None())
|
||||
{
|
||||
Color c = item.prefab.SpriteColor;
|
||||
Color c = item.Prefab.SpriteColor;
|
||||
item.SpriteColor = new Color(c.R / 255f * m, c.G / 255f * m, c.B / 255f * m, c.A / 255f);
|
||||
}
|
||||
}
|
||||
foreach (var structure in thalamusStructures)
|
||||
{
|
||||
Color c = structure.prefab.SpriteColor;
|
||||
Color c = structure.Prefab.SpriteColor;
|
||||
structure.SpriteColor = new Color(c.R / 255f * m, c.G / 255f * m, c.B / 255f * m, c.A / 255f);
|
||||
}
|
||||
yield return CoroutineStatus.Running;
|
||||
@@ -42,7 +42,7 @@ namespace Barotrauma
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||
{
|
||||
IsAlive = msg.ReadBoolean();
|
||||
}
|
||||
|
||||
@@ -469,7 +469,7 @@ namespace Barotrauma
|
||||
Color? color = null;
|
||||
if (character.ExternalHighlight)
|
||||
{
|
||||
color = Color.Lerp(Color.White, GUI.Style.Orange, (float)Math.Sin(Timing.TotalTime * 3.5f));
|
||||
color = Color.Lerp(Color.White, GUIStyle.Orange, (float)Math.Sin(Timing.TotalTime * 3.5f));
|
||||
}
|
||||
|
||||
float depthOffset = GetDepthOffset();
|
||||
@@ -564,7 +564,7 @@ namespace Barotrauma
|
||||
Vector2 pos = ConvertUnits.ToDisplayUnits(limb.PullJointWorldAnchorB);
|
||||
if (currentHull?.Submarine != null) pos += currentHull.Submarine.DrawPosition;
|
||||
pos.Y = -pos.Y;
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)pos.Y, 5, 5), GUI.Style.Red, true, 0.01f);
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)pos.Y, 5, 5), GUIStyle.Red, true, 0.01f);
|
||||
|
||||
pos = ConvertUnits.ToDisplayUnits(limb.PullJointWorldAnchorA);
|
||||
if (currentHull?.Submarine != null) pos += currentHull.Submarine.DrawPosition;
|
||||
@@ -575,8 +575,8 @@ namespace Barotrauma
|
||||
limb.body.DebugDraw(spriteBatch, inWater ? (currentHull == null ? Color.Blue : Color.Cyan) : Color.White);
|
||||
}
|
||||
|
||||
Collider.DebugDraw(spriteBatch, frozen ? GUI.Style.Red : (inWater ? Color.SkyBlue : Color.Gray));
|
||||
GUI.Font.DrawString(spriteBatch, Collider.LinearVelocity.X.FormatSingleDecimal(), new Vector2(Collider.DrawPosition.X, -Collider.DrawPosition.Y), Color.Orange);
|
||||
Collider.DebugDraw(spriteBatch, frozen ? GUIStyle.Red : (inWater ? Color.SkyBlue : Color.Gray));
|
||||
GUIStyle.Font.DrawString(spriteBatch, Collider.LinearVelocity.X.FormatSingleDecimal(), new Vector2(Collider.DrawPosition.X, -Collider.DrawPosition.Y), Color.Orange);
|
||||
|
||||
foreach (var joint in LimbJoints)
|
||||
{
|
||||
@@ -607,10 +607,10 @@ namespace Barotrauma
|
||||
{
|
||||
Vector2 pos = ConvertUnits.ToDisplayUnits(humanoid.RightHandIKPos);
|
||||
if (humanoid.character.Submarine != null) { pos += humanoid.character.Submarine.DrawPosition; }
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 4, 4), GUI.Style.Green, true);
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 4, 4), GUIStyle.Green, true);
|
||||
pos = ConvertUnits.ToDisplayUnits(humanoid.LeftHandIKPos);
|
||||
if (humanoid.character.Submarine != null) { pos += humanoid.character.Submarine.DrawPosition; }
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 4, 4), GUI.Style.Green, true);
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 4, 4), GUIStyle.Green, true);
|
||||
|
||||
Vector2 aimPos = humanoid.AimSourceWorldPos;
|
||||
aimPos.Y = -aimPos.Y;
|
||||
|
||||
@@ -6,22 +6,22 @@ namespace Barotrauma
|
||||
{
|
||||
partial class Attack
|
||||
{
|
||||
[Serialize("StructureBlunt", true), Editable()]
|
||||
[Serialize("StructureBlunt", IsPropertySaveable.Yes), Editable()]
|
||||
public string StructureSoundType { get; private set; }
|
||||
|
||||
private RoundSound sound;
|
||||
|
||||
private ParticleEmitter particleEmitter;
|
||||
|
||||
partial void InitProjSpecific(XElement element)
|
||||
partial void InitProjSpecific(ContentXElement element)
|
||||
{
|
||||
if (element.Attribute("sound") != null)
|
||||
if (element.GetAttribute("sound") != null)
|
||||
{
|
||||
DebugConsole.ThrowError("Error in attack ("+element+") - sounds should be defined as child elements, not as attributes.");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
@@ -29,7 +29,7 @@ namespace Barotrauma
|
||||
particleEmitter = new ParticleEmitter(subElement);
|
||||
break;
|
||||
case "sound":
|
||||
sound = Submarine.LoadRoundSound(subElement);
|
||||
sound = RoundSound.Load(subElement);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ namespace Barotrauma
|
||||
private class GUIMessage
|
||||
{
|
||||
public string RawText;
|
||||
public string Identifier;
|
||||
public Identifier Identifier;
|
||||
public string Text;
|
||||
|
||||
private int _value;
|
||||
@@ -142,7 +142,7 @@ namespace Barotrauma
|
||||
{
|
||||
_value = value;
|
||||
Text = RawText.Replace("[value]", _value.ToString());
|
||||
Size = GUI.Font.MeasureString(Text);
|
||||
Size = GUIStyle.Font.MeasureString(Text);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ namespace Barotrauma
|
||||
|
||||
public bool PlaySound;
|
||||
|
||||
public GUIMessage(string rawText, Color color, float delay, string identifier = null, int? value = null, float lifeTime = 3.0f)
|
||||
public GUIMessage(string rawText, Color color, float delay, Identifier identifier = default, int? value = null, float lifeTime = 3.0f)
|
||||
{
|
||||
RawText = Text = rawText;
|
||||
if (value.HasValue)
|
||||
@@ -163,7 +163,7 @@ namespace Barotrauma
|
||||
Value = value.Value;
|
||||
}
|
||||
Timer = -delay;
|
||||
Size = GUI.Font.MeasureString(Text);
|
||||
Size = GUIStyle.Font.MeasureString(Text);
|
||||
Color = color;
|
||||
Identifier = identifier;
|
||||
Lifetime = lifeTime;
|
||||
@@ -202,14 +202,14 @@ namespace Barotrauma
|
||||
get { return activeObjectiveEntities; }
|
||||
}
|
||||
|
||||
partial void InitProjSpecific(XElement mainElement)
|
||||
partial void InitProjSpecific(ContentXElement mainElement)
|
||||
{
|
||||
soundTimer = Rand.Range(0.0f, Params.SoundInterval);
|
||||
|
||||
sounds = new List<CharacterSound>();
|
||||
Params.Sounds.ForEach(s => sounds.Add(new CharacterSound(s)));
|
||||
|
||||
foreach (XElement subElement in mainElement.Elements())
|
||||
foreach (var subElement in mainElement.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
@@ -267,11 +267,11 @@ namespace Barotrauma
|
||||
//and the fire key is the same as Select or Use, reset the key to prevent accidentally selecting/using items
|
||||
if (wasFiring && !keys[(int)InputType.Shoot].Held)
|
||||
{
|
||||
if (GameMain.Config.KeyBind(InputType.Shoot).Equals(GameMain.Config.KeyBind(InputType.Select)))
|
||||
if (GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Shoot] == GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Select])
|
||||
{
|
||||
keys[(int)InputType.Select].Reset();
|
||||
}
|
||||
if (GameMain.Config.KeyBind(InputType.Shoot).Equals(GameMain.Config.KeyBind(InputType.Use)))
|
||||
if (GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Shoot] == GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Use])
|
||||
{
|
||||
keys[(int)InputType.Use].Reset();
|
||||
}
|
||||
@@ -331,7 +331,7 @@ namespace Barotrauma
|
||||
Position +
|
||||
PlayerInput.MouseSpeed.ClampLength(10.0f); //apply a little bit of movement to the cursor pos to prevent AFK kicking
|
||||
}
|
||||
else if (!GameMain.Config.EnableMouseLook)
|
||||
else if (!GameSettings.CurrentConfig.EnableMouseLook)
|
||||
{
|
||||
cam.OffsetAmount = targetOffsetAmount = 0.0f;
|
||||
}
|
||||
@@ -446,15 +446,15 @@ namespace Barotrauma
|
||||
|
||||
if (GameMain.NetworkMember != null && controlled == this)
|
||||
{
|
||||
string chatMessage = CauseOfDeath.Type == CauseOfDeathType.Affliction ?
|
||||
LocalizedString chatMessage = CauseOfDeath.Type == CauseOfDeathType.Affliction ?
|
||||
CauseOfDeath.Affliction.SelfCauseOfDeathDescription :
|
||||
TextManager.Get("Self_CauseOfDeathDescription." + CauseOfDeath.Type.ToString(), fallBackTag: "Self_CauseOfDeathDescription.Damage");
|
||||
TextManager.Get("Self_CauseOfDeathDescription." + CauseOfDeath.Type.ToString(), "Self_CauseOfDeathDescription.Damage");
|
||||
|
||||
if (GameMain.Client != null) { chatMessage += " " + TextManager.Get("DeathChatNotification"); }
|
||||
|
||||
GameMain.NetworkMember.RespawnManager?.ShowRespawnPromptIfNeeded();
|
||||
|
||||
GameMain.NetworkMember.AddChatMessage(chatMessage, ChatMessageType.Dead);
|
||||
GameMain.NetworkMember.AddChatMessage(chatMessage.Value, ChatMessageType.Dead);
|
||||
GameMain.LightManager.LosEnabled = false;
|
||||
controlled = null;
|
||||
if (!(Screen.Selected?.Cam is null))
|
||||
@@ -726,9 +726,9 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
partial void SetOrderProjSpecific(Order order, string orderOption, int priority)
|
||||
partial void SetOrderProjSpecific(Order order)
|
||||
{
|
||||
GameMain.GameSession?.CrewManager?.AddCurrentOrderIcon(this, order, orderOption, priority);
|
||||
GameMain.GameSession?.CrewManager?.AddCurrentOrderIcon(this, order);
|
||||
}
|
||||
|
||||
public static void AddAllToGUIUpdateList()
|
||||
@@ -812,7 +812,7 @@ namespace Barotrauma
|
||||
Controlled != this &&
|
||||
Submarine != null &&
|
||||
Controlled.Submarine == Submarine &&
|
||||
GameMain.Config.LosMode != LosMode.None)
|
||||
GameSettings.CurrentConfig.Graphics.LosMode != LosMode.None)
|
||||
{
|
||||
float yPos = Controlled.AnimController.FloorY - 1.5f;
|
||||
|
||||
@@ -854,7 +854,7 @@ namespace Barotrauma
|
||||
|
||||
if (speechBubbleTimer > 0.0f)
|
||||
{
|
||||
GUI.SpeechBubbleIcon.Draw(spriteBatch, pos - Vector2.UnitY * 5,
|
||||
GUIStyle.SpeechBubbleIcon.Value.Sprite.Draw(spriteBatch, pos - Vector2.UnitY * 5,
|
||||
speechBubbleColor * Math.Min(speechBubbleTimer, 1.0f), 0.0f,
|
||||
Math.Min(speechBubbleTimer, 1.0f));
|
||||
}
|
||||
@@ -880,7 +880,7 @@ namespace Barotrauma
|
||||
GUI.DrawLine(spriteBatch,
|
||||
cursorPos,
|
||||
new Vector2(item.DrawPosition.X, -item.DrawPosition.Y),
|
||||
ToolBox.GradientLerp(dist, GUI.Style.Red, GUI.Style.Orange, GUI.Style.Green), width: 2);
|
||||
ToolBox.GradientLerp(dist, GUIStyle.Red, GUIStyle.Orange, GUIStyle.Green), width: 2);
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -899,10 +899,10 @@ namespace Barotrauma
|
||||
{
|
||||
if (info != null)
|
||||
{
|
||||
string name = Info.DisplayName;
|
||||
LocalizedString name = Info.DisplayName;
|
||||
if (controlled == null && name != Info.Name) { name += " " + TextManager.Get("Disguised"); }
|
||||
|
||||
Vector2 nameSize = GUI.Font.MeasureString(name);
|
||||
Vector2 nameSize = GUIStyle.Font.MeasureString(name);
|
||||
Vector2 namePos = new Vector2(pos.X, pos.Y - 10.0f - (5.0f / cam.Zoom)) - nameSize * 0.5f / cam.Zoom;
|
||||
Color nameColor = GetNameColor();
|
||||
|
||||
@@ -916,7 +916,7 @@ namespace Barotrauma
|
||||
|
||||
if (CampaignInteractionType != CampaignMode.InteractionType.None && AllowCustomInteract)
|
||||
{
|
||||
var iconStyle = GUI.Style.GetComponentStyle("CampaignInteractionBubble." + CampaignInteractionType);
|
||||
var iconStyle = GUIStyle.GetComponentStyle("CampaignInteractionBubble." + CampaignInteractionType);
|
||||
if (iconStyle != null)
|
||||
{
|
||||
Vector2 headPos = AnimController.GetLimb(LimbType.Head)?.body?.DrawPosition ?? DrawPosition + Vector2.UnitY * 100.0f;
|
||||
@@ -929,11 +929,11 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
GUI.Font.DrawString(spriteBatch, name, namePos + new Vector2(1.0f / cam.Zoom, 1.0f / cam.Zoom), Color.Black, 0.0f, Vector2.Zero, 1.0f / cam.Zoom, SpriteEffects.None, 0.001f);
|
||||
GUI.Font.DrawString(spriteBatch, name, namePos, nameColor * hudInfoAlpha, 0.0f, Vector2.Zero, 1.0f / cam.Zoom, SpriteEffects.None, 0.0f);
|
||||
GUIStyle.Font.DrawString(spriteBatch, name, namePos + new Vector2(1.0f / cam.Zoom, 1.0f / cam.Zoom), Color.Black, 0.0f, Vector2.Zero, 1.0f / cam.Zoom, SpriteEffects.None, 0.001f);
|
||||
GUIStyle.Font.DrawString(spriteBatch, name, namePos, nameColor * hudInfoAlpha, 0.0f, Vector2.Zero, 1.0f / cam.Zoom, SpriteEffects.None, 0.0f);
|
||||
if (GameMain.DebugDraw)
|
||||
{
|
||||
GUI.Font.DrawString(spriteBatch, ID.ToString(), namePos - new Vector2(0.0f, 20.0f), Color.White);
|
||||
GUIStyle.Font.DrawString(spriteBatch, ID.ToString(), namePos - new Vector2(0.0f, 20.0f), Color.White);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -941,7 +941,7 @@ namespace Barotrauma
|
||||
if (petBehavior != null && !IsDead && !IsUnconscious)
|
||||
{
|
||||
var petStatus = petBehavior.GetCurrentStatusIndicatorType();
|
||||
var iconStyle = GUI.Style.GetComponentStyle("PetIcon." + petStatus);
|
||||
var iconStyle = GUIStyle.GetComponentStyle("PetIcon." + petStatus);
|
||||
if (iconStyle != null)
|
||||
{
|
||||
Vector2 headPos = AnimController.GetLimb(LimbType.Head)?.body?.DrawPosition ?? DrawPosition + Vector2.UnitY * 100.0f;
|
||||
@@ -963,7 +963,7 @@ namespace Barotrauma
|
||||
Vector2 healthBarPos = new Vector2(pos.X - 50, -pos.Y);
|
||||
GUI.DrawProgressBar(spriteBatch, healthBarPos, new Vector2(100.0f, 15.0f),
|
||||
CharacterHealth.DisplayedVitality / MaxVitality,
|
||||
Color.Lerp(GUI.Style.Red, GUI.Style.Green, CharacterHealth.DisplayedVitality / MaxVitality) * 0.8f * hudInfoAlpha,
|
||||
Color.Lerp(GUIStyle.Red, GUIStyle.Green, CharacterHealth.DisplayedVitality / MaxVitality) * 0.8f * hudInfoAlpha,
|
||||
new Color(0.5f, 0.57f, 0.6f, 1.0f) * hudInfoAlpha);
|
||||
}
|
||||
}
|
||||
@@ -987,7 +987,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
Color nameColor = GUI.Style.TextColor;
|
||||
Color nameColor = GUIStyle.TextColorNormal;
|
||||
if (Controlled != null && team != Controlled.TeamID)
|
||||
{
|
||||
if (TeamID == CharacterTeamType.FriendlyNPC)
|
||||
@@ -996,13 +996,13 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
nameColor = GUI.Style.Red;
|
||||
nameColor = GUIStyle.Red;
|
||||
}
|
||||
}
|
||||
return nameColor;
|
||||
}
|
||||
|
||||
public void AddMessage(string rawText, Color color, bool playSound, string identifier = null, int? value = null, float lifetime = 3.0f)
|
||||
public void AddMessage(string rawText, Color color, bool playSound, Identifier identifier = default, int? value = null, float lifetime = 3.0f)
|
||||
{
|
||||
GUIMessage existingMessage = null;
|
||||
|
||||
@@ -1089,12 +1089,12 @@ namespace Barotrauma
|
||||
matchingSounds.Clear();
|
||||
foreach (var s in sounds)
|
||||
{
|
||||
if (s.Type == soundType && (s.Gender == Gender.None || (info != null && info.Gender == s.Gender)))
|
||||
if (s.Type == soundType && (s.TagSet.None() || (info != null && s.TagSet.IsSubsetOf(info.Head.Preset.TagSet))))
|
||||
{
|
||||
matchingSounds.Add(s);
|
||||
}
|
||||
}
|
||||
var selectedSound = matchingSounds.GetRandom();
|
||||
var selectedSound = matchingSounds.GetRandomUnsynced();
|
||||
if (selectedSound?.Sound == null) { return; }
|
||||
soundChannel = SoundPlayer.PlaySound(selectedSound.Sound, AnimController.WorldPosition, selectedSound.Volume, selectedSound.Range, hullGuess: CurrentHull, ignoreMuffling: selectedSound.IgnoreMuffling);
|
||||
soundTimer = Params.SoundInterval;
|
||||
@@ -1117,7 +1117,7 @@ namespace Barotrauma
|
||||
/// <summary>
|
||||
/// Note that when a predicate is provided, the random option uses Linq.Where() extension method, which creates a new collection.
|
||||
/// </summary>
|
||||
public CharacterSound GetSound(Func<CharacterSound, bool> predicate = null, bool random = false) => random ? sounds.GetRandom(predicate) : sounds.FirstOrDefault(predicate);
|
||||
public CharacterSound GetSound(Func<CharacterSound, bool> predicate = null, bool random = false) => random ? sounds.GetRandomUnsynced(predicate) : sounds.FirstOrDefault(predicate);
|
||||
|
||||
partial void ImplodeFX()
|
||||
{
|
||||
@@ -1151,19 +1151,11 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
partial void OnMoneyChanged(int prevAmount, int newAmount)
|
||||
{
|
||||
if (newAmount > prevAmount)
|
||||
{
|
||||
int increase = newAmount - prevAmount;
|
||||
AddMessage("+" + TextManager.GetWithVariable("currencyformat", "[credits]", "[value]"),
|
||||
GUI.Style.Yellow, playSound: this == Controlled, "money", increase);
|
||||
}
|
||||
}
|
||||
partial void OnMoneyChanged(int prevAmount, int newAmount) { }
|
||||
|
||||
partial void OnTalentGiven(TalentPrefab talentPrefab)
|
||||
{
|
||||
AddMessage(TextManager.Get("talentname." + talentPrefab.Identifier), GUI.Style.Yellow, playSound: this == Controlled);
|
||||
AddMessage(TextManager.Get("talentname." + talentPrefab.Identifier).Value, GUIStyle.Yellow, playSound: this == Controlled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,23 +35,23 @@ namespace Barotrauma
|
||||
MinSize = new Point(100, 50),
|
||||
RelativeOffset = new Vector2(0.0f, 0.01f)
|
||||
}, isHorizontal: false, childAnchor: Anchor.TopCenter);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.4f), TopContainer.RectTransform), character.DisplayName, textAlignment: Alignment.Center, textColor: GUI.Style.Red);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.4f), TopContainer.RectTransform), character.DisplayName, textAlignment: Alignment.Center, textColor: GUIStyle.Red);
|
||||
TopHealthBar = new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.6f), TopContainer.RectTransform)
|
||||
{
|
||||
MinSize = new Point(100, HUDLayoutSettings.HealthBarArea.Size.Y)
|
||||
}, barSize: 0.0f, style: "CharacterHealthBarCentered")
|
||||
{
|
||||
Color = GUI.Style.Red
|
||||
Color = GUIStyle.Red
|
||||
};
|
||||
|
||||
SideContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), bossHealthContainer.RectTransform)
|
||||
{
|
||||
MinSize = new Point(80, 60)
|
||||
}, isHorizontal: false, childAnchor: Anchor.TopRight);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), SideContainer.RectTransform), character.DisplayName, textAlignment: Alignment.CenterRight, textColor: GUI.Style.Red);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), SideContainer.RectTransform), character.DisplayName, textAlignment: Alignment.CenterRight, textColor: GUIStyle.Red);
|
||||
SideHealthBar = new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.7f), SideContainer.RectTransform), barSize: 0.0f, style: "CharacterHealthBar")
|
||||
{
|
||||
Color = GUI.Style.Red
|
||||
Color = GUIStyle.Red
|
||||
};
|
||||
|
||||
TopContainer.Visible = SideContainer.Visible = false;
|
||||
@@ -72,7 +72,7 @@ namespace Barotrauma
|
||||
|
||||
private static readonly List<BossHealthBar> bossHealthBars = new List<BossHealthBar>();
|
||||
|
||||
private static readonly Dictionary<string, string> cachedHudTexts = new Dictionary<string, string>();
|
||||
private static readonly Dictionary<Identifier, LocalizedString> cachedHudTexts = new Dictionary<Identifier, LocalizedString>();
|
||||
|
||||
private static GUILayoutGroup bossHealthContainer;
|
||||
|
||||
@@ -119,14 +119,12 @@ namespace Barotrauma
|
||||
!ConversationAction.FadeScreenToBlack;
|
||||
}
|
||||
|
||||
public static string GetCachedHudText(string textTag, string keyBind)
|
||||
public static LocalizedString GetCachedHudText(string textTag, InputType keyBind)
|
||||
{
|
||||
if (cachedHudTexts.TryGetValue(textTag + keyBind, out string text))
|
||||
{
|
||||
return text;
|
||||
}
|
||||
text = TextManager.GetWithVariable(textTag, "[key]", keyBind);
|
||||
cachedHudTexts.Add(textTag + keyBind, text);
|
||||
Identifier key = (textTag + keyBind).ToIdentifier();
|
||||
if (cachedHudTexts.TryGetValue(key, out LocalizedString text)) { return text; }
|
||||
text = TextManager.GetWithVariable(textTag, "[key]", GameSettings.CurrentConfig.KeyMap.KeyBindText(keyBind)).Value;
|
||||
cachedHudTexts.Add(key, text);
|
||||
return text;
|
||||
}
|
||||
|
||||
@@ -256,24 +254,24 @@ namespace Barotrauma
|
||||
if (GameMain.GameSession?.CrewManager != null)
|
||||
{
|
||||
orderIndicatorCount.Clear();
|
||||
foreach (Pair<Order, float?> activeOrder in GameMain.GameSession.CrewManager.ActiveOrders)
|
||||
foreach (CrewManager.ActiveOrder activeOrder in GameMain.GameSession.CrewManager.ActiveOrders)
|
||||
{
|
||||
if (!DrawIcon(activeOrder.First)) { continue; }
|
||||
if (!DrawIcon(activeOrder.Order)) { continue; }
|
||||
|
||||
if (activeOrder.Second.HasValue)
|
||||
if (activeOrder.FadeOutTime.HasValue)
|
||||
{
|
||||
DrawOrderIndicator(spriteBatch, cam, character, activeOrder.First, iconAlpha: MathHelper.Clamp(activeOrder.Second.Value / 10.0f, 0.2f, 1.0f));
|
||||
DrawOrderIndicator(spriteBatch, cam, character, activeOrder.Order, iconAlpha: MathHelper.Clamp(activeOrder.FadeOutTime.Value / 10.0f, 0.2f, 1.0f));
|
||||
}
|
||||
else
|
||||
{
|
||||
float iconAlpha = GetDistanceBasedIconAlpha(activeOrder.First.TargetSpatialEntity, maxDistance: 450.0f);
|
||||
float iconAlpha = GetDistanceBasedIconAlpha(activeOrder.Order.TargetSpatialEntity, maxDistance: 450.0f);
|
||||
if (iconAlpha <= 0.0f) { continue; }
|
||||
DrawOrderIndicator(spriteBatch, cam, character, activeOrder.First,
|
||||
DrawOrderIndicator(spriteBatch, cam, character, activeOrder.Order,
|
||||
iconAlpha: iconAlpha, createOffset: false, scaleMultiplier: 0.5f, overrideAlpha: true);
|
||||
}
|
||||
}
|
||||
|
||||
if (character.GetCurrentOrderWithTopPriority()?.Order is Order currentOrder && DrawIcon(currentOrder))
|
||||
if (character.GetCurrentOrderWithTopPriority() is Order currentOrder && DrawIcon(currentOrder))
|
||||
{
|
||||
DrawOrderIndicator(spriteBatch, cam, character, currentOrder, 1.0f);
|
||||
}
|
||||
@@ -310,8 +308,8 @@ namespace Barotrauma
|
||||
if (!brokenItem.IsInteractable(character)) { continue; }
|
||||
float alpha = GetDistanceBasedIconAlpha(brokenItem);
|
||||
if (alpha <= 0.0f) continue;
|
||||
GUI.DrawIndicator(spriteBatch, brokenItem.DrawPosition, cam, 100.0f, GUI.BrokenIcon,
|
||||
Color.Lerp(GUI.Style.Red, GUI.Style.Orange * 0.5f, brokenItem.Condition / brokenItem.MaxCondition) * alpha);
|
||||
GUI.DrawIndicator(spriteBatch, brokenItem.DrawPosition, cam, 100.0f, GUIStyle.BrokenIcon.Value.Sprite,
|
||||
Color.Lerp(GUIStyle.Red, GUIStyle.Orange * 0.5f, brokenItem.Condition / brokenItem.MaxCondition) * alpha);
|
||||
}
|
||||
|
||||
float GetDistanceBasedIconAlpha(ISpatialEntity target, float maxDistance = 1000.0f)
|
||||
@@ -344,12 +342,12 @@ namespace Barotrauma
|
||||
circleSize = MathHelper.Clamp(circleSize, 45.0f, 100.0f) * Math.Min((focusedItemOverlayTimer - 1.0f) * 5.0f, 1.0f);
|
||||
if (circleSize > 0.0f)
|
||||
{
|
||||
Vector2 scale = new Vector2(circleSize / GUI.Style.FocusIndicator.FrameSize.X);
|
||||
GUI.Style.FocusIndicator.Draw(spriteBatch,
|
||||
(int)((focusedItemOverlayTimer - 1.0f) * GUI.Style.FocusIndicator.FrameCount * 3.0f),
|
||||
Vector2 scale = new Vector2(circleSize / GUIStyle.FocusIndicator.FrameSize.X);
|
||||
GUIStyle.FocusIndicator.Draw(spriteBatch,
|
||||
(int)((focusedItemOverlayTimer - 1.0f) * GUIStyle.FocusIndicator.FrameCount * 3.0f),
|
||||
circlePos,
|
||||
Color.LightBlue * 0.3f,
|
||||
origin: GUI.Style.FocusIndicator.FrameSize.ToVector2() / 2,
|
||||
origin: GUIStyle.FocusIndicator.FrameSize.ToVector2() / 2,
|
||||
rotate: (float)Timing.TotalTime,
|
||||
scale: scale);
|
||||
}
|
||||
@@ -367,8 +365,8 @@ namespace Barotrauma
|
||||
|
||||
int dir = Math.Sign(focusedItem.WorldPosition.X - character.WorldPosition.X);
|
||||
|
||||
Vector2 textSize = GUI.Font.MeasureString(hudTexts.First().Text);
|
||||
Vector2 largeTextSize = GUI.SubHeadingFont.MeasureString(hudTexts.First().Text);
|
||||
Vector2 textSize = GUIStyle.Font.MeasureString(hudTexts.First().Text);
|
||||
Vector2 largeTextSize = GUIStyle.SubHeadingFont.MeasureString(hudTexts.First().Text);
|
||||
|
||||
Vector2 startPos = cam.WorldToScreen(focusedItem.DrawPosition);
|
||||
startPos.Y -= (hudTexts.Count + 1) * textSize.Y;
|
||||
@@ -383,14 +381,14 @@ namespace Barotrauma
|
||||
|
||||
float alpha = MathHelper.Clamp((focusedItemOverlayTimer - ItemOverlayDelay) * 2.0f, 0.0f, 1.0f);
|
||||
|
||||
GUI.DrawString(spriteBatch, textPos, hudTexts.First().Text, hudTexts.First().Color * alpha, Color.Black * alpha * 0.7f, 2, font: GUI.SubHeadingFont);
|
||||
GUI.DrawString(spriteBatch, textPos, hudTexts.First().Text, hudTexts.First().Color * alpha, Color.Black * alpha * 0.7f, 2, font: GUIStyle.SubHeadingFont, ForceUpperCase.No);
|
||||
startPos.X += dir * 10.0f * GUI.Scale;
|
||||
textPos.X += dir * 10.0f * GUI.Scale;
|
||||
textPos.Y += largeTextSize.Y;
|
||||
foreach (ColoredText coloredText in hudTexts.Skip(1))
|
||||
{
|
||||
if (dir == -1) textPos.X = (int)(startPos.X - GUI.SmallFont.MeasureString(coloredText.Text).X);
|
||||
GUI.DrawString(spriteBatch, textPos, coloredText.Text, coloredText.Color * alpha, Color.Black * alpha * 0.7f, 2, GUI.SmallFont);
|
||||
if (dir == -1) textPos.X = (int)(startPos.X - GUIStyle.SmallFont.MeasureString(coloredText.Text).X);
|
||||
GUI.DrawString(spriteBatch, textPos, coloredText.Text, coloredText.Color * alpha, Color.Black * alpha * 0.7f, 2, GUIStyle.SmallFont);
|
||||
textPos.Y += textSize.Y;
|
||||
}
|
||||
}
|
||||
@@ -405,7 +403,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (npc.CampaignInteractionType == CampaignMode.InteractionType.None || npc.Submarine != character.Submarine || npc.IsDead || npc.IsIncapacitated) { continue; }
|
||||
|
||||
var iconStyle = GUI.Style.GetComponentStyle("CampaignInteractionIcon." + npc.CampaignInteractionType);
|
||||
var iconStyle = GUIStyle.GetComponentStyle("CampaignInteractionIcon." + npc.CampaignInteractionType);
|
||||
if (iconStyle == null) { continue; }
|
||||
Range<float> visibleRange = new Range<float>(npc.CurrentHull == Character.Controlled.CurrentHull ? 500.0f : 100.0f, float.PositiveInfinity);
|
||||
if (npc.CampaignInteractionType == CampaignMode.InteractionType.Examine)
|
||||
@@ -486,12 +484,14 @@ namespace Barotrauma
|
||||
(int)(HUDLayoutSettings.BottomRightInfoArea.Y + HUDLayoutSettings.BottomRightInfoArea.Height * 0.1f),
|
||||
(int)(HUDLayoutSettings.BottomRightInfoArea.Width / 2),
|
||||
(int)(HUDLayoutSettings.BottomRightInfoArea.Height * 0.7f)), character.Info.IsDisguisedAsAnother);
|
||||
character.Info.DrawPortrait(spriteBatch, HUDLayoutSettings.PortraitArea.Location.ToVector2(), new Vector2(-12 * GUI.Scale, 4 * GUI.Scale), targetWidth: HUDLayoutSettings.PortraitArea.Width, true, character.Info.IsDisguisedAsAnother);
|
||||
float yOffset = (GameMain.GameSession?.Campaign is MultiPlayerCampaign ? -10 : 4) * GUI.Scale;
|
||||
character.Info.DrawPortrait(spriteBatch, HUDLayoutSettings.PortraitArea.Location.ToVector2(), new Vector2(-12 * GUI.Scale, yOffset), targetWidth: HUDLayoutSettings.PortraitArea.Width, true, character.Info.IsDisguisedAsAnother);
|
||||
character.Info.DrawForeground(spriteBatch);
|
||||
}
|
||||
mouseOnPortrait = HUDLayoutSettings.BottomRightInfoArea.Contains(PlayerInput.MousePosition) && !character.ShouldLockHud();
|
||||
if (mouseOnPortrait)
|
||||
{
|
||||
GUI.UIGlow.Draw(spriteBatch, HUDLayoutSettings.BottomRightInfoArea, GUI.Style.Green * 0.5f);
|
||||
GUIStyle.UIGlow.Draw(spriteBatch, HUDLayoutSettings.BottomRightInfoArea, GUIStyle.Green * 0.5f);
|
||||
}
|
||||
}
|
||||
if (ShouldDrawInventory(character))
|
||||
@@ -555,28 +555,28 @@ namespace Barotrauma
|
||||
|
||||
string focusName = character.FocusedCharacter.Info == null ? character.FocusedCharacter.DisplayName : character.FocusedCharacter.Info.DisplayName;
|
||||
Vector2 textPos = startPos;
|
||||
Vector2 textSize = GUI.Font.MeasureString(focusName);
|
||||
Vector2 largeTextSize = GUI.SubHeadingFont.MeasureString(focusName);
|
||||
Vector2 textSize = GUIStyle.Font.MeasureString(focusName);
|
||||
Vector2 largeTextSize = GUIStyle.SubHeadingFont.MeasureString(focusName);
|
||||
|
||||
textPos -= new Vector2(textSize.X / 2, textSize.Y);
|
||||
|
||||
Color nameColor = character.FocusedCharacter.GetNameColor();
|
||||
GUI.DrawString(spriteBatch, textPos, focusName, nameColor, Color.Black * 0.7f, 2, GUI.SubHeadingFont);
|
||||
GUI.DrawString(spriteBatch, textPos, focusName, nameColor, Color.Black * 0.7f, 2, GUIStyle.SubHeadingFont, ForceUpperCase.No);
|
||||
textPos.X += 10.0f * GUI.Scale;
|
||||
textPos.Y += GUI.SubHeadingFont.MeasureString(focusName).Y;
|
||||
textPos.Y += GUIStyle.SubHeadingFont.MeasureString(focusName).Y;
|
||||
|
||||
if (!character.FocusedCharacter.IsIncapacitated && character.FocusedCharacter.IsPet)
|
||||
{
|
||||
GUI.DrawString(spriteBatch, textPos, GetCachedHudText("PlayHint", GameMain.Config.KeyBindText(InputType.Use)),
|
||||
GUI.Style.Green, Color.Black, 2, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, textPos, GetCachedHudText("PlayHint", InputType.Use),
|
||||
GUIStyle.Green, Color.Black, 2, GUIStyle.SmallFont);
|
||||
textPos.Y += largeTextSize.Y;
|
||||
}
|
||||
|
||||
if (character.FocusedCharacter.CanBeDragged)
|
||||
{
|
||||
string text = character.CanEat ? "EatHint" : "GrabHint";
|
||||
GUI.DrawString(spriteBatch, textPos, GetCachedHudText(text, GameMain.Config.KeyBindText(InputType.Grab)),
|
||||
GUI.Style.Green, Color.Black, 2, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, textPos, GetCachedHudText(text, InputType.Grab),
|
||||
GUIStyle.Green, Color.Black, 2, GUIStyle.SmallFont);
|
||||
textPos.Y += largeTextSize.Y;
|
||||
}
|
||||
|
||||
@@ -585,13 +585,13 @@ namespace Barotrauma
|
||||
character.FocusedCharacter.CharacterHealth.UseHealthWindow &&
|
||||
character.CanInteractWith(character.FocusedCharacter, 160f, false))
|
||||
{
|
||||
GUI.DrawString(spriteBatch, textPos, GetCachedHudText("HealHint", GameMain.Config.KeyBindText(InputType.Health)),
|
||||
GUI.Style.Green, Color.Black, 2, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, textPos, GetCachedHudText("HealHint", InputType.Health),
|
||||
GUIStyle.Green, Color.Black, 2, GUIStyle.SmallFont);
|
||||
textPos.Y += textSize.Y;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(character.FocusedCharacter.customInteractHUDText) && character.FocusedCharacter.AllowCustomInteract)
|
||||
if (!character.FocusedCharacter.CustomInteractHUDText.IsNullOrEmpty() && character.FocusedCharacter.AllowCustomInteract)
|
||||
{
|
||||
GUI.DrawString(spriteBatch, textPos, character.FocusedCharacter.customInteractHUDText, GUI.Style.Green, Color.Black, 2, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, textPos, character.FocusedCharacter.CustomInteractHUDText, GUIStyle.Green, Color.Black, 2, GUIStyle.SmallFont);
|
||||
textPos.Y += textSize.Y;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ using Microsoft.Xna.Framework.Graphics;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.IO;
|
||||
using Barotrauma.Items.Components;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -34,17 +35,17 @@ namespace Barotrauma
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
infoAreaPortraitBG = GUI.Style.GetComponentStyle("InfoAreaPortraitBG")?.GetDefaultSprite();
|
||||
infoAreaPortraitBG = GUIStyle.GetComponentStyle("InfoAreaPortraitBG")?.GetDefaultSprite();
|
||||
new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(833, 298, 142, 98), null, 0);
|
||||
}
|
||||
|
||||
partial void LoadHeadSpriteProjectSpecific(XElement limbElement)
|
||||
partial void LoadHeadSpriteProjectSpecific(ContentXElement limbElement)
|
||||
{
|
||||
XElement maskElement = limbElement.Element("tintmask");
|
||||
ContentXElement maskElement = limbElement.GetChildElement("tintmask");
|
||||
if (maskElement != null)
|
||||
{
|
||||
string tintMaskPath = maskElement.GetAttributeString("texture", "");
|
||||
if (!string.IsNullOrWhiteSpace(tintMaskPath))
|
||||
ContentPath tintMaskPath = maskElement.GetAttributeContentPath("texture");
|
||||
if (!tintMaskPath.IsNullOrEmpty())
|
||||
{
|
||||
tintMask = new Sprite(maskElement, file: Limb.GetSpritePath(tintMaskPath, this));
|
||||
tintHighlightThreshold = maskElement.GetAttributeFloat("highlightthreshold", 0.6f);
|
||||
@@ -66,7 +67,7 @@ namespace Barotrauma
|
||||
new GUICustomComponent(new RectTransform(new Vector2(0.425f, 1.0f), headerArea.RectTransform),
|
||||
onDraw: (sb, component) => DrawInfoFrameCharacterIcon(sb, component.Rect));
|
||||
|
||||
ScalableFont font = paddedFrame.Rect.Width < 280 ? GUI.SmallFont : GUI.Font;
|
||||
GUIFont font = paddedFrame.Rect.Width < 280 ? GUIStyle.SmallFont : GUIStyle.Font;
|
||||
|
||||
var headerTextArea = new GUILayoutGroup(new RectTransform(new Vector2(0.575f, 1.0f), headerArea.RectTransform))
|
||||
{
|
||||
@@ -77,9 +78,9 @@ namespace Barotrauma
|
||||
Color? nameColor = null;
|
||||
if (Job != null) { nameColor = Job.Prefab.UIColor; }
|
||||
|
||||
GUITextBlock characterNameBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), headerTextArea.RectTransform), ToolBox.LimitString(Name, GUI.Font, headerTextArea.Rect.Width), textColor: nameColor, font: GUI.Font)
|
||||
GUITextBlock characterNameBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), headerTextArea.RectTransform), ToolBox.LimitString(Name, GUIStyle.Font, headerTextArea.Rect.Width), textColor: nameColor, font: GUIStyle.Font)
|
||||
{
|
||||
ForceUpperCase = true,
|
||||
ForceUpperCase = ForceUpperCase.Yes,
|
||||
Padding = Vector4.Zero
|
||||
};
|
||||
|
||||
@@ -98,9 +99,11 @@ namespace Barotrauma
|
||||
};
|
||||
}
|
||||
|
||||
if (personalityTrait != null)
|
||||
if (PersonalityTrait != null)
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), headerTextArea.RectTransform), TextManager.AddPunctuation(':', TextManager.Get("PersonalityTrait"), TextManager.Get("personalitytrait." + personalityTrait.Name.Replace(" ", ""))), font: font)
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), headerTextArea.RectTransform),
|
||||
TextManager.AddPunctuation(':', TextManager.Get("PersonalityTrait"), TextManager.Get("personalitytrait." + PersonalityTrait.Name.Replace(" ".ToIdentifier(), "".ToIdentifier()))),
|
||||
font: font)
|
||||
{
|
||||
Padding = Vector4.Zero
|
||||
};
|
||||
@@ -148,10 +151,10 @@ namespace Barotrauma
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
string deadDescription = TextManager.AddPunctuation(':', TextManager.Get("deceased") + "\n" + Character.CauseOfDeath.Affliction?.CauseOfDeathDescription ??
|
||||
LocalizedString deadDescription = TextManager.AddPunctuation(':', TextManager.Get("deceased") + "\n" + Character.CauseOfDeath.Affliction?.CauseOfDeathDescription ??
|
||||
TextManager.AddPunctuation(':', TextManager.Get("CauseOfDeath"), TextManager.Get("CauseOfDeath." + Character.CauseOfDeath.Type.ToString())));
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), deadArea.RectTransform), deadDescription, textColor: GUI.Style.Red, font: font, textAlignment: Alignment.TopLeft) { Padding = Vector4.Zero };
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), deadArea.RectTransform), deadDescription, textColor: GUIStyle.Red, font: font, textAlignment: Alignment.TopLeft) { Padding = Vector4.Zero };
|
||||
}
|
||||
|
||||
if (returnParent)
|
||||
@@ -182,13 +185,13 @@ namespace Barotrauma
|
||||
Color? textColor = null;
|
||||
if (Job != null) { textColor = Job.Prefab.UIColor; }
|
||||
|
||||
GUITextBlock textBlock = new GUITextBlock(new RectTransform(Vector2.One, frame.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point(40, 0) }, text, textColor: textColor, font: GUI.SmallFont);
|
||||
GUITextBlock textBlock = new GUITextBlock(new RectTransform(Vector2.One, frame.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point(40, 0) }, text, textColor: textColor, font: GUIStyle.SmallFont);
|
||||
new GUICustomComponent(new RectTransform(new Point(frame.Rect.Height, frame.Rect.Height), frame.RectTransform, Anchor.CenterLeft) { IsFixedSize = false },
|
||||
onDraw: (sb, component) => DrawIcon(sb, component.Rect.Center.ToVector2(), targetAreaSize: component.Rect.Size.ToVector2()));
|
||||
return frame;
|
||||
}
|
||||
|
||||
partial void OnSkillChanged(string skillIdentifier, float prevLevel, float newLevel)
|
||||
partial void OnSkillChanged(Identifier skillIdentifier, float prevLevel, float newLevel)
|
||||
{
|
||||
if (TeamID == CharacterTeamType.FriendlyNPC) { return; }
|
||||
if (Character.Controlled != null && Character.Controlled.TeamID != TeamID) { return; }
|
||||
@@ -199,9 +202,10 @@ namespace Barotrauma
|
||||
if ((int)newLevel > (int)prevLevel)
|
||||
{
|
||||
int increase = Math.Max((int)newLevel - (int)prevLevel, 1);
|
||||
|
||||
Character?.AddMessage(
|
||||
"+[value] "+ TextManager.Get("SkillName." + skillIdentifier),
|
||||
specialIncrease ? GUI.Style.Orange : GUI.Style.Green,
|
||||
"+[value] "+ TextManager.Get("SkillName." + skillIdentifier).Value,
|
||||
specialIncrease ? GUIStyle.Orange : GUIStyle.Green,
|
||||
playSound: Character == Character.Controlled, skillIdentifier, increase);
|
||||
}
|
||||
}
|
||||
@@ -216,8 +220,8 @@ namespace Barotrauma
|
||||
{
|
||||
int increase = newAmount - prevAmount;
|
||||
Character?.AddMessage(
|
||||
"+[value] " + TextManager.Get("experienceshort"),
|
||||
GUI.Style.Blue, playSound: Character == Character.Controlled, "exp", increase);
|
||||
"+[value] " + TextManager.Get("experienceshort").Value,
|
||||
GUIStyle.Blue, playSound: Character == Character.Controlled, "exp".ToIdentifier(), increase);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,9 +231,13 @@ namespace Barotrauma
|
||||
|
||||
if (idCard.StoredOwnerAppearance.JobPrefab == null || idCard.StoredOwnerAppearance.Portrait == null)
|
||||
{
|
||||
string[] readTags = idCard.Item.Tags.Split(',');
|
||||
var readTags = idCard.Item.Tags.Split(',')
|
||||
.Where(s => s.Contains(':'))
|
||||
.Select(s => s.Split(':'))
|
||||
.Select(s => (s[0].ToIdentifier(),s[1]))
|
||||
.ToImmutableDictionary();
|
||||
|
||||
if (readTags.Length == 0) { return; }
|
||||
if (readTags.None()) { return; }
|
||||
|
||||
if (idCard.StoredOwnerAppearance.JobPrefab == null)
|
||||
{
|
||||
@@ -238,7 +246,7 @@ namespace Barotrauma
|
||||
|
||||
if (idCard.StoredOwnerAppearance.Portrait == null)
|
||||
{
|
||||
idCard.StoredOwnerAppearance.ExtractAppearance(this, readTags);
|
||||
idCard.StoredOwnerAppearance.ExtractAppearance(this, idCard);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,17 +275,17 @@ namespace Barotrauma
|
||||
{
|
||||
LoadHeadAttachments();
|
||||
}
|
||||
FaceAttachment?.Elements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.FaceAttachment)));
|
||||
BeardElement?.Elements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.Beard)));
|
||||
MoustacheElement?.Elements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.Moustache)));
|
||||
HairElement?.Elements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.Hair)));
|
||||
Head.FaceAttachment?.GetChildElements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.FaceAttachment)));
|
||||
Head.BeardElement?.GetChildElements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.Beard)));
|
||||
Head.MoustacheElement?.GetChildElements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.Moustache)));
|
||||
Head.HairElement?.GetChildElements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.Hair)));
|
||||
if (omitJob)
|
||||
{
|
||||
JobPrefab.NoJobElement?.Element("PortraitClothing")?.Elements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.JobIndicator)));
|
||||
JobPrefab.NoJobElement?.GetChildElement("PortraitClothing")?.GetChildElements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.JobIndicator)));
|
||||
}
|
||||
else
|
||||
{
|
||||
Job?.Prefab.ClothingElement?.Elements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.JobIndicator)));
|
||||
Job?.Prefab.ClothingElement?.GetChildElements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.JobIndicator)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,7 +296,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (sprite == null) { return; }
|
||||
if (Head.SheetIndex == null) { return; }
|
||||
Point location = CalculateOffset(sprite, Head.SheetIndex.Value.ToPoint());
|
||||
Point location = CalculateOffset(sprite, Head.SheetIndex.ToPoint());
|
||||
sprite.SourceRect = new Rectangle(location, sprite.SourceRect.Size);
|
||||
}
|
||||
|
||||
@@ -301,6 +309,32 @@ namespace Barotrauma
|
||||
HUDLayoutSettings.BottomRightInfoArea.Height / (float)infoAreaPortraitBG.SourceRect.Height));
|
||||
}
|
||||
|
||||
public void DrawForeground(SpriteBatch spriteBatch)
|
||||
{
|
||||
if (Character is null || GameMain.IsSingleplayer) { return; }
|
||||
const int million = 1000000;
|
||||
int xfraction = (int)(HUDLayoutSettings.BottomRightInfoArea.Width * 0.2f);
|
||||
int yoffset = GUI.IntScale(6);
|
||||
|
||||
int walletAmount = Character.Wallet.Balance;
|
||||
|
||||
LocalizedString str = walletAmount >= million ? TextManager.Get("crewwallet.balance.toomuchtoshow") : TextManager.FormatCurrency(walletAmount);
|
||||
Vector2 size = GUIStyle.Font.MeasureString(str);
|
||||
int barHeight = GUI.IntScale(18);
|
||||
|
||||
Rectangle barRect = new Rectangle((int)(HUDLayoutSettings.BottomRightInfoArea.X + xfraction / 2.5f), HUDLayoutSettings.BottomRightInfoArea.Bottom - barHeight - yoffset, HUDLayoutSettings.BottomRightInfoArea.Width - xfraction, barHeight);
|
||||
float textScale = Math.Max(0.1f, Math.Min(barRect.Width / size.X, barRect.Height / size.Y)) - 0.01f;
|
||||
|
||||
GUIStyle.WalletPortraitBG.Draw(spriteBatch, barRect, Color.White);
|
||||
|
||||
int iconSize = GUI.IntScale(28);
|
||||
int iconXOffset = iconSize / 2;
|
||||
Rectangle iconRect = new Rectangle(barRect.Right - iconXOffset, barRect.Top - iconSize / 4, iconSize, iconSize);
|
||||
GUIStyle.CrewWalletIconSmall.Draw(spriteBatch, iconRect, Color.White);
|
||||
var (scaledTextSizeX, scaledTextSizeY) = size * textScale;
|
||||
GUIStyle.Font.DrawString(spriteBatch, str, new Vector2(barRect.Right - iconXOffset - scaledTextSizeX - GUI.IntScale(4), barRect.Center.Y - scaledTextSizeY / 2), GUIStyle.TextColorNormal, 0f, Vector2.Zero, textScale, SpriteEffects.None, 0f);
|
||||
}
|
||||
|
||||
public void DrawPortrait(SpriteBatch spriteBatch, Vector2 screenPos, Vector2 offset, float targetWidth, bool flip = false, bool evaluateDisguise = false)
|
||||
{
|
||||
if (evaluateDisguise && IsDisguised) { return; }
|
||||
@@ -414,19 +448,16 @@ namespace Barotrauma
|
||||
{
|
||||
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.SourceRect = new Rectangle(CalculateOffset(headSprite, Head.SheetIndex.ToPoint()), headSprite.SourceRect.Size);
|
||||
SetHeadEffect(spriteBatch);
|
||||
headSprite.Draw(spriteBatch, screenPos, scale: scale, color: SkinColor);
|
||||
headSprite.Draw(spriteBatch, screenPos, scale: scale, color: Head.SkinColor);
|
||||
if (AttachmentSprites != null)
|
||||
{
|
||||
float depthStep = 0.000001f;
|
||||
foreach (var attachment in AttachmentSprites)
|
||||
{
|
||||
SetAttachmentEffect(spriteBatch, attachment);
|
||||
DrawAttachmentSprite(spriteBatch, attachment, headSprite, Head.SheetIndex, screenPos, scale, depthStep, GetAttachmentColor(attachment, HairColor, FacialHairColor));
|
||||
DrawAttachmentSprite(spriteBatch, attachment, headSprite, Head.SheetIndex, screenPos, scale, depthStep, GetAttachmentColor(attachment, Head.HairColor, Head.FacialHairColor));
|
||||
depthStep += depthStep;
|
||||
}
|
||||
}
|
||||
@@ -479,14 +510,17 @@ namespace Barotrauma
|
||||
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)
|
||||
public static CharacterInfo ClientRead(Identifier speciesName, IReadMessage inc)
|
||||
{
|
||||
ushort infoID = inc.ReadUInt16();
|
||||
string newName = inc.ReadString();
|
||||
string originalName = inc.ReadString();
|
||||
int gender = inc.ReadByte();
|
||||
int race = inc.ReadByte();
|
||||
int headSpriteID = inc.ReadByte();
|
||||
int tagCount = inc.ReadByte();
|
||||
HashSet<Identifier> tagSet = new HashSet<Identifier>();
|
||||
for (int i = 0; i < tagCount; i++)
|
||||
{
|
||||
tagSet.Add(inc.ReadIdentifier());
|
||||
}
|
||||
int hairIndex = inc.ReadByte();
|
||||
int beardIndex = inc.ReadByte();
|
||||
int moustacheIndex = inc.ReadByte();
|
||||
@@ -500,14 +534,14 @@ namespace Barotrauma
|
||||
int variant = inc.ReadByte();
|
||||
|
||||
JobPrefab jobPrefab = null;
|
||||
Dictionary<string, float> skillLevels = new Dictionary<string, float>();
|
||||
Dictionary<Identifier, float> skillLevels = new Dictionary<Identifier, float>();
|
||||
if (!string.IsNullOrEmpty(jobIdentifier))
|
||||
{
|
||||
jobPrefab = JobPrefab.Get(jobIdentifier);
|
||||
byte skillCount = inc.ReadByte();
|
||||
for (int i = 0; i < skillCount; i++)
|
||||
{
|
||||
string skillIdentifier = inc.ReadString();
|
||||
Identifier skillIdentifier = inc.ReadIdentifier();
|
||||
float skillLevel = inc.ReadSingle();
|
||||
skillLevels.Add(skillIdentifier, skillLevel);
|
||||
}
|
||||
@@ -518,14 +552,14 @@ namespace Barotrauma
|
||||
{
|
||||
ID = infoID,
|
||||
};
|
||||
ch.RecreateHead(headSpriteID,(Race)race, (Gender)gender, hairIndex, beardIndex, moustacheIndex, faceAttachmentIndex);
|
||||
ch.SkinColor = skinColor;
|
||||
ch.HairColor = hairColor;
|
||||
ch.FacialHairColor = facialHairColor;
|
||||
ch.RecreateHead(tagSet.ToImmutableHashSet(), hairIndex, beardIndex, moustacheIndex, faceAttachmentIndex);
|
||||
ch.Head.SkinColor = skinColor;
|
||||
ch.Head.HairColor = hairColor;
|
||||
ch.Head.FacialHairColor = facialHairColor;
|
||||
ch.SetPersonalityTrait();
|
||||
if (ch.Job != null)
|
||||
{
|
||||
foreach (KeyValuePair<string, float> skill in skillLevels)
|
||||
foreach (KeyValuePair<Identifier, float> skill in skillLevels)
|
||||
{
|
||||
Skill matchingSkill = ch.Job.Skills.Find(s => s.Identifier == skill.Key);
|
||||
if (matchingSkill == null)
|
||||
@@ -538,17 +572,8 @@ namespace Barotrauma
|
||||
ch.Job.Skills.RemoveAll(s => !skillLevels.ContainsKey(s.Identifier));
|
||||
}
|
||||
|
||||
byte savedStatValueCount = inc.ReadByte();
|
||||
for (int i = 0; i < savedStatValueCount; i++)
|
||||
{
|
||||
int statType = inc.ReadByte();
|
||||
string statIdentifier = inc.ReadString();
|
||||
float statValue = inc.ReadSingle();
|
||||
bool removeOnDeath = inc.ReadBoolean();
|
||||
ch.ChangeSavedStatValue((StatTypes)statType, statValue, statIdentifier, removeOnDeath);
|
||||
}
|
||||
ch.ExperiencePoints = inc.ReadUInt16();
|
||||
ch.AdditionalTalentPoints = inc.ReadUInt16();
|
||||
ch.AdditionalTalentPoints = inc.ReadRangedInteger(0, MaxAdditionalTalentPoints);
|
||||
return ch;
|
||||
}
|
||||
|
||||
@@ -605,12 +630,12 @@ namespace Barotrauma
|
||||
{ RelativeOffset = new Vector2(-0.01f, 0.0f) });
|
||||
}
|
||||
|
||||
RectTransform createItemRectTransform(string labelTag, float width = 0.6f)
|
||||
RectTransform createItemRectTransform(Identifier labelTag, float width = 0.6f)
|
||||
{
|
||||
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);
|
||||
TextManager.Get(labelTag), font: GUIStyle.SubHeadingFont);
|
||||
|
||||
var bottomItem = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.5f), layoutGroup.RectTransform),
|
||||
style: null);
|
||||
@@ -618,43 +643,40 @@ namespace Barotrauma
|
||||
return new RectTransform(new Vector2(width, 1.0f), bottomItem.RectTransform, Anchor.Center);
|
||||
}
|
||||
|
||||
RectTransform genderItemRT = createItemRectTransform("Gender", 1.0f);
|
||||
RectTransform menuCategoryRT = createItemRectTransform(info.Prefab.MenuCategoryVar, 1.0f);
|
||||
|
||||
GUILayoutGroup genderContainer =
|
||||
new GUILayoutGroup(genderItemRT, isHorizontal: true)
|
||||
GUILayoutGroup menuCategoryContainer =
|
||||
new GUILayoutGroup(menuCategoryRT, isHorizontal: true)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.05f
|
||||
};
|
||||
|
||||
void createGenderButton(Gender gender)
|
||||
void createMenuCategoryButton(Identifier tag)
|
||||
{
|
||||
new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), genderContainer.RectTransform),
|
||||
TextManager.Get(gender.ToString()), style: "ListBoxElement")
|
||||
new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), menuCategoryContainer.RectTransform),
|
||||
TextManager.Get(tag), style: "ListBoxElement")
|
||||
{
|
||||
UserData = gender,
|
||||
UserData = tag,
|
||||
OnClicked = OpenHeadSelection,
|
||||
Selected = info.Gender == gender
|
||||
Selected = info.Head.Preset.TagSet.Contains(tag)
|
||||
};
|
||||
}
|
||||
|
||||
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();
|
||||
foreach (var tag in info.Prefab.VarTags[info.Prefab.MenuCategoryVar].OrderBy(t => t.Value).Reverse())
|
||||
{
|
||||
createMenuCategoryButton(tag);
|
||||
}
|
||||
|
||||
List<GUIScrollBar> attachmentSliders = new List<GUIScrollBar>();
|
||||
void createAttachmentSlider(int initialValue, WearableType wearableType)
|
||||
{
|
||||
int attachmentCount = countAttachmentsOfType(wearableType);
|
||||
int attachmentCount = info.CountValidAttachmentsOfType(wearableType);
|
||||
if (attachmentCount > 0)
|
||||
{
|
||||
var labelTag = wearableType == WearableType.FaceAttachment
|
||||
? "FaceAttachment.Accessories"
|
||||
: $"FaceAttachment.{wearableType}";
|
||||
? "FaceAttachment.Accessories".ToIdentifier()
|
||||
: $"FaceAttachment.{wearableType}".ToIdentifier();
|
||||
var sliderItemRT = createItemRectTransform(labelTag);
|
||||
var slider =
|
||||
new GUIScrollBar(sliderItemRT, style: "GUISlider")
|
||||
@@ -670,12 +692,12 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
createAttachmentSlider(info.HairIndex, WearableType.Hair);
|
||||
createAttachmentSlider(info.BeardIndex, WearableType.Beard);
|
||||
createAttachmentSlider(info.MoustacheIndex, WearableType.Moustache);
|
||||
createAttachmentSlider(info.FaceAttachmentIndex, WearableType.FaceAttachment);
|
||||
createAttachmentSlider(info.Head.HairIndex, WearableType.Hair);
|
||||
createAttachmentSlider(info.Head.BeardIndex, WearableType.Beard);
|
||||
createAttachmentSlider(info.Head.MoustacheIndex, WearableType.Moustache);
|
||||
createAttachmentSlider(info.Head.FaceAttachmentIndex, WearableType.FaceAttachment);
|
||||
|
||||
void createColorSelector(string labelTag, IEnumerable<(Color Color, float Commonness)> options, Func<Color> getter,
|
||||
void createColorSelector(Identifier labelTag, IEnumerable<(Color Color, float Commonness)> options, Func<Color> getter,
|
||||
Action<Color> setter)
|
||||
{
|
||||
var selectorItemRT = createItemRectTransform(labelTag, 0.4f);
|
||||
@@ -757,21 +779,21 @@ namespace Barotrauma
|
||||
};
|
||||
}
|
||||
|
||||
if (countAttachmentsOfType(WearableType.Hair) > 0)
|
||||
if (info.CountValidAttachmentsOfType(WearableType.Hair) > 0)
|
||||
{
|
||||
createColorSelector($"Customization.{nameof(info.HairColor)}", info.HairColors,
|
||||
() => info.HairColor, (color) => info.HairColor = color);
|
||||
createColorSelector($"Customization.{nameof(info.Head.HairColor)}".ToIdentifier(), info.HairColors,
|
||||
() => info.Head.HairColor, (color) => info.Head.HairColor = color);
|
||||
}
|
||||
|
||||
if (countAttachmentsOfType(WearableType.Moustache) > 0 ||
|
||||
countAttachmentsOfType(WearableType.Beard) > 0)
|
||||
if (info.CountValidAttachmentsOfType(WearableType.Moustache) > 0 ||
|
||||
info.CountValidAttachmentsOfType(WearableType.Beard) > 0)
|
||||
{
|
||||
createColorSelector($"Customization.{nameof(info.FacialHairColor)}", info.FacialHairColors,
|
||||
() => info.FacialHairColor, (color) => info.FacialHairColor = color);
|
||||
createColorSelector($"Customization.{nameof(info.Head.FacialHairColor)}".ToIdentifier(), info.FacialHairColors,
|
||||
() => info.Head.FacialHairColor, (color) => info.Head.FacialHairColor = color);
|
||||
}
|
||||
|
||||
createColorSelector($"Customization.{nameof(info.SkinColor)}", info.SkinColors, () => info.SkinColor,
|
||||
(color) => info.SkinColor = color);
|
||||
|
||||
createColorSelector($"Customization.{nameof(info.Head.SkinColor)}".ToIdentifier(), info.SkinColors, () => info.Head.SkinColor,
|
||||
(color) => info.Head.SkinColor = color);
|
||||
|
||||
RandomizeButton = new GUIButton(new RectTransform(Vector2.One * 0.12f,
|
||||
parentComponent.RectTransform,
|
||||
@@ -780,10 +802,11 @@ namespace Barotrauma
|
||||
{
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
info.Head = new HeadInfo();
|
||||
info.SetGenderAndRace(Rand.RandSync.Unsynced);
|
||||
info.SetColors();
|
||||
|
||||
var headPreset = info.Prefab.Heads.GetRandom(Rand.RandSync.Unsynced);
|
||||
info.Head = new HeadInfo(info, headPreset);
|
||||
info.SetAttachments(Rand.RandSync.Unsynced);
|
||||
info.SetColors(Rand.RandSync.Unsynced);
|
||||
|
||||
RecreateFrameContents();
|
||||
info.RefreshHead();
|
||||
OnHeadSwitch?.Invoke(this);
|
||||
@@ -801,7 +824,7 @@ namespace Barotrauma
|
||||
|
||||
private bool OpenHeadSelection(GUIButton button, object userData)
|
||||
{
|
||||
Gender selectedGender = (Gender)userData;
|
||||
Identifier selectedCategory = (Identifier)userData;
|
||||
|
||||
var info = CharacterInfo;
|
||||
|
||||
@@ -842,36 +865,27 @@ namespace Barotrauma
|
||||
GUILayoutGroup row = null;
|
||||
int itemsInRow = 0;
|
||||
|
||||
XElement headElement = info.Ragdoll.MainElement.Elements().FirstOrDefault(e =>
|
||||
ContentXElement 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;
|
||||
ContentXElement headSpriteElement = headElement.GetChildElement("sprite");
|
||||
ContentPath spritePathWithTags = headSpriteElement.GetAttributeContentPath("texture");
|
||||
|
||||
var characterConfigElement = info.CharacterConfigElement;
|
||||
|
||||
var heads = info.Heads;
|
||||
var heads = info.Prefab.Heads;
|
||||
if (heads != null)
|
||||
{
|
||||
row = null;
|
||||
itemsInRow = 0;
|
||||
foreach (var kvp in heads.Where(kv => kv.Key.Gender == selectedGender))
|
||||
foreach (var head in heads.Where(h => h.TagSet.Contains(selectedCategory)))
|
||||
{
|
||||
var headPreset = kvp.Key;
|
||||
Race race = headPreset.Race;
|
||||
int headIndex = headPreset.ID;
|
||||
string spritePath = info.Prefab.ReplaceVars(spritePathWithTags.Value, head);
|
||||
|
||||
string spritePath = spritePathWithTags
|
||||
.Replace("[GENDER]", selectedGender.ToString().ToLowerInvariant())
|
||||
.Replace("[RACE]", race.ToString().ToLowerInvariant());
|
||||
|
||||
if (!File.Exists(spritePath))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!File.Exists(spritePath)) { continue; }
|
||||
|
||||
Sprite headSprite = new Sprite(headSpriteElement, "", spritePath);
|
||||
headSprite.SourceRect =
|
||||
new Rectangle(CalculateOffset(headSprite, kvp.Value.ToPoint()),
|
||||
new Rectangle(CharacterInfo.CalculateOffset(headSprite, head.SheetIndex.ToPoint()),
|
||||
headSprite.SourceRect.Size);
|
||||
characterSprites.Add(headSprite);
|
||||
|
||||
@@ -881,7 +895,7 @@ namespace Barotrauma
|
||||
new RectTransform(new Vector2(1.0f, 0.333f), HeadSelectionList.Content.RectTransform),
|
||||
true)
|
||||
{
|
||||
UserData = selectedGender,
|
||||
UserData = head.MenuCategory,
|
||||
Visible = true
|
||||
};
|
||||
itemsInRow = 0;
|
||||
@@ -892,9 +906,9 @@ namespace Barotrauma
|
||||
{
|
||||
OutlineColor = Color.White * 0.5f,
|
||||
PressedColor = Color.White * 0.5f,
|
||||
UserData = new Tuple<Gender, Race, int>(selectedGender, race, headIndex),
|
||||
UserData = head,
|
||||
OnClicked = SwitchHead,
|
||||
Selected = selectedGender == info.Gender && race == info.Race && headIndex == info.HeadSpriteId,
|
||||
Selected = info.Head.Preset == head,
|
||||
Visible = true
|
||||
};
|
||||
|
||||
@@ -909,12 +923,18 @@ namespace Barotrauma
|
||||
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.Head.HeadSpriteId = id;
|
||||
var headPreset = obj as HeadPreset;
|
||||
if (info.Head.Preset != headPreset)
|
||||
{
|
||||
info.Head = new HeadInfo(info, headPreset)
|
||||
{
|
||||
SkinColor = info.Head.SkinColor,
|
||||
HairColor = info.Head.HairColor,
|
||||
FacialHairColor = info.Head.FacialHairColor
|
||||
};
|
||||
info.ReloadHeadAttachments();
|
||||
}
|
||||
|
||||
RecreateFrameContents();
|
||||
OnHeadSwitch?.Invoke(this);
|
||||
return true;
|
||||
@@ -927,16 +947,16 @@ namespace Barotrauma
|
||||
switch (type)
|
||||
{
|
||||
case WearableType.Beard:
|
||||
info.BeardIndex = index;
|
||||
info.Head.BeardIndex = index;
|
||||
break;
|
||||
case WearableType.FaceAttachment:
|
||||
info.FaceAttachmentIndex = index;
|
||||
info.Head.FaceAttachmentIndex = index;
|
||||
break;
|
||||
case WearableType.Hair:
|
||||
info.HairIndex = index;
|
||||
info.Head.HairIndex = index;
|
||||
break;
|
||||
case WearableType.Moustache:
|
||||
info.MoustacheIndex = index;
|
||||
info.Head.MoustacheIndex = index;
|
||||
break;
|
||||
default:
|
||||
DebugConsole.ThrowError($"Wearable type not implemented: {type}");
|
||||
|
||||
@@ -112,395 +112,404 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
||||
public void ClientWriteInput(IWriteMessage msg)
|
||||
{
|
||||
if (extraData != null)
|
||||
msg.Write((byte)ClientNetObject.CHARACTER_INPUT);
|
||||
|
||||
if (memInput.Count > 60)
|
||||
{
|
||||
switch ((NetEntityEvent.Type)extraData[0])
|
||||
memInput.RemoveRange(60, memInput.Count - 60);
|
||||
}
|
||||
|
||||
msg.Write(LastNetworkUpdateID);
|
||||
byte inputCount = Math.Min((byte)memInput.Count, (byte)60);
|
||||
msg.Write(inputCount);
|
||||
for (int i = 0; i < inputCount; i++)
|
||||
{
|
||||
msg.WriteRangedInteger((int)memInput[i].states, 0, (int)InputNetFlags.MaxVal);
|
||||
msg.Write(memInput[i].intAim);
|
||||
if (memInput[i].states.HasFlag(InputNetFlags.Select) ||
|
||||
memInput[i].states.HasFlag(InputNetFlags.Deselect) ||
|
||||
memInput[i].states.HasFlag(InputNetFlags.Use) ||
|
||||
memInput[i].states.HasFlag(InputNetFlags.Health) ||
|
||||
memInput[i].states.HasFlag(InputNetFlags.Grab))
|
||||
{
|
||||
case NetEntityEvent.Type.InventoryState:
|
||||
msg.WriteRangedInteger(0, 0, 4);
|
||||
Inventory.ClientWrite(msg, extraData);
|
||||
break;
|
||||
case NetEntityEvent.Type.Treatment:
|
||||
msg.WriteRangedInteger(1, 0, 4);
|
||||
msg.Write(AnimController.Anim == AnimController.Animation.CPR);
|
||||
break;
|
||||
case NetEntityEvent.Type.Status:
|
||||
msg.WriteRangedInteger(2, 0, 4);
|
||||
break;
|
||||
case NetEntityEvent.Type.UpdateTalents:
|
||||
msg.WriteRangedInteger(3, 0, 4);
|
||||
msg.Write((ushort)characterTalents.Count);
|
||||
foreach (var unlockedTalent in characterTalents)
|
||||
{
|
||||
msg.Write(unlockedTalent.Prefab.UIntIdentifier);
|
||||
}
|
||||
break;
|
||||
msg.Write(memInput[i].interact);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
|
||||
{
|
||||
if (!(extraData is IEventData eventData)) { throw new Exception($"Malformed character event: expected {nameof(Character)}.{nameof(IEventData)}"); }
|
||||
|
||||
msg.WriteRangedInteger((int)eventData.EventType, (int)EventType.MinValue, (int)EventType.MaxValue);
|
||||
switch (eventData)
|
||||
{
|
||||
case InventoryStateEventData inventoryStateEventData:
|
||||
Inventory.ClientEventWrite(msg, inventoryStateEventData);
|
||||
break;
|
||||
case TreatmentEventData _:
|
||||
msg.Write(AnimController.Anim == AnimController.Animation.CPR);
|
||||
break;
|
||||
case CharacterStatusEventData _:
|
||||
//do nothing
|
||||
break;
|
||||
case UpdateTalentsEventData _:
|
||||
msg.Write((ushort)characterTalents.Count);
|
||||
foreach (var unlockedTalent in characterTalents)
|
||||
{
|
||||
msg.Write(unlockedTalent.Prefab.UintIdentifier);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new Exception($"Malformed character event: did not expect {eventData.GetType().Name}");
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientReadPosition(IReadMessage msg, float sendingTime)
|
||||
{
|
||||
bool facingRight = AnimController.Dir > 0.0f;
|
||||
|
||||
lastRecvPositionUpdateTime = (float)Lidgren.Network.NetTime.Now;
|
||||
|
||||
AnimController.Frozen = false;
|
||||
Enabled = true;
|
||||
|
||||
UInt16 networkUpdateID = 0;
|
||||
if (msg.ReadBoolean())
|
||||
{
|
||||
networkUpdateID = msg.ReadUInt16();
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.Write((byte)ClientNetObject.CHARACTER_INPUT);
|
||||
bool aimInput = msg.ReadBoolean();
|
||||
keys[(int)InputType.Aim].Held = aimInput;
|
||||
keys[(int)InputType.Aim].SetState(false, aimInput);
|
||||
|
||||
if (memInput.Count > 60)
|
||||
bool shootInput = msg.ReadBoolean();
|
||||
keys[(int)InputType.Shoot].Held = shootInput;
|
||||
keys[(int)InputType.Shoot].SetState(false, shootInput);
|
||||
|
||||
bool useInput = msg.ReadBoolean();
|
||||
keys[(int)InputType.Use].Held = useInput;
|
||||
keys[(int)InputType.Use].SetState(false, useInput);
|
||||
|
||||
if (AnimController is HumanoidAnimController)
|
||||
{
|
||||
memInput.RemoveRange(60, memInput.Count - 60);
|
||||
bool crouching = msg.ReadBoolean();
|
||||
keys[(int)InputType.Crouch].Held = crouching;
|
||||
keys[(int)InputType.Crouch].SetState(false, crouching);
|
||||
}
|
||||
|
||||
msg.Write(LastNetworkUpdateID);
|
||||
byte inputCount = Math.Min((byte)memInput.Count, (byte)60);
|
||||
msg.Write(inputCount);
|
||||
for (int i = 0; i < inputCount; i++)
|
||||
{
|
||||
msg.WriteRangedInteger((int)memInput[i].states, 0, (int)InputNetFlags.MaxVal);
|
||||
msg.Write(memInput[i].intAim);
|
||||
if (memInput[i].states.HasFlag(InputNetFlags.Select) ||
|
||||
memInput[i].states.HasFlag(InputNetFlags.Deselect) ||
|
||||
memInput[i].states.HasFlag(InputNetFlags.Use) ||
|
||||
memInput[i].states.HasFlag(InputNetFlags.Health) ||
|
||||
memInput[i].states.HasFlag(InputNetFlags.Grab))
|
||||
{
|
||||
msg.Write(memInput[i].interact);
|
||||
}
|
||||
}
|
||||
bool attackInput = msg.ReadBoolean();
|
||||
keys[(int)InputType.Attack].Held = attackInput;
|
||||
keys[(int)InputType.Attack].SetState(false, attackInput);
|
||||
|
||||
double aimAngle = msg.ReadUInt16() / 65535.0 * 2.0 * Math.PI;
|
||||
cursorPosition = AimRefPosition + new Vector2((float)Math.Cos(aimAngle), (float)Math.Sin(aimAngle)) * 500.0f;
|
||||
TransformCursorPos();
|
||||
|
||||
bool ragdollInput = msg.ReadBoolean();
|
||||
keys[(int)InputType.Ragdoll].Held = ragdollInput;
|
||||
keys[(int)InputType.Ragdoll].SetState(false, ragdollInput);
|
||||
|
||||
facingRight = msg.ReadBoolean();
|
||||
}
|
||||
msg.WritePadBits();
|
||||
}
|
||||
|
||||
public virtual void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||
{
|
||||
switch (type)
|
||||
bool entitySelected = msg.ReadBoolean();
|
||||
Character selectedCharacter = null;
|
||||
Item selectedItem = null;
|
||||
|
||||
AnimController.Animation animation = AnimController.Animation.None;
|
||||
if (entitySelected)
|
||||
{
|
||||
case ServerNetObject.ENTITY_POSITION:
|
||||
bool facingRight = AnimController.Dir > 0.0f;
|
||||
|
||||
lastRecvPositionUpdateTime = (float)Lidgren.Network.NetTime.Now;
|
||||
|
||||
AnimController.Frozen = false;
|
||||
Enabled = true;
|
||||
|
||||
UInt16 networkUpdateID = 0;
|
||||
if (msg.ReadBoolean())
|
||||
ushort characterID = msg.ReadUInt16();
|
||||
ushort itemID = msg.ReadUInt16();
|
||||
selectedCharacter = FindEntityByID(characterID) as Character;
|
||||
selectedItem = FindEntityByID(itemID) as Item;
|
||||
if (characterID != NullEntityID)
|
||||
{
|
||||
bool doingCpr = msg.ReadBoolean();
|
||||
if (doingCpr && SelectedCharacter != null)
|
||||
{
|
||||
networkUpdateID = msg.ReadUInt16();
|
||||
animation = AnimController.Animation.CPR;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool aimInput = msg.ReadBoolean();
|
||||
keys[(int)InputType.Aim].Held = aimInput;
|
||||
keys[(int)InputType.Aim].SetState(false, aimInput);
|
||||
|
||||
bool shootInput = msg.ReadBoolean();
|
||||
keys[(int)InputType.Shoot].Held = shootInput;
|
||||
keys[(int)InputType.Shoot].SetState(false, shootInput);
|
||||
|
||||
bool useInput = msg.ReadBoolean();
|
||||
keys[(int)InputType.Use].Held = useInput;
|
||||
keys[(int)InputType.Use].SetState(false, useInput);
|
||||
|
||||
if (AnimController is HumanoidAnimController)
|
||||
{
|
||||
bool crouching = msg.ReadBoolean();
|
||||
keys[(int)InputType.Crouch].Held = crouching;
|
||||
keys[(int)InputType.Crouch].SetState(false, crouching);
|
||||
}
|
||||
|
||||
bool attackInput = msg.ReadBoolean();
|
||||
keys[(int)InputType.Attack].Held = attackInput;
|
||||
keys[(int)InputType.Attack].SetState(false, attackInput);
|
||||
|
||||
double aimAngle = msg.ReadUInt16() / 65535.0 * 2.0 * Math.PI;
|
||||
cursorPosition = AimRefPosition + new Vector2((float)Math.Cos(aimAngle), (float)Math.Sin(aimAngle)) * 500.0f;
|
||||
TransformCursorPos();
|
||||
|
||||
bool ragdollInput = msg.ReadBoolean();
|
||||
keys[(int)InputType.Ragdoll].Held = ragdollInput;
|
||||
keys[(int)InputType.Ragdoll].SetState(false, ragdollInput);
|
||||
|
||||
facingRight = msg.ReadBoolean();
|
||||
}
|
||||
|
||||
bool entitySelected = msg.ReadBoolean();
|
||||
Character selectedCharacter = null;
|
||||
Item selectedItem = null;
|
||||
|
||||
AnimController.Animation animation = AnimController.Animation.None;
|
||||
if (entitySelected)
|
||||
{
|
||||
ushort characterID = msg.ReadUInt16();
|
||||
ushort itemID = msg.ReadUInt16();
|
||||
selectedCharacter = FindEntityByID(characterID) as Character;
|
||||
selectedItem = FindEntityByID(itemID) as Item;
|
||||
if (characterID != NullEntityID)
|
||||
{
|
||||
bool doingCpr = msg.ReadBoolean();
|
||||
if (doingCpr && SelectedCharacter != null)
|
||||
{
|
||||
animation = AnimController.Animation.CPR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vector2 pos = new Vector2(
|
||||
msg.ReadSingle(),
|
||||
msg.ReadSingle());
|
||||
float MaxVel = NetConfig.MaxPhysicsBodyVelocity;
|
||||
Vector2 linearVelocity = new Vector2(
|
||||
msg.ReadRangedSingle(-MaxVel, MaxVel, 12),
|
||||
msg.ReadRangedSingle(-MaxVel, MaxVel, 12));
|
||||
linearVelocity = NetConfig.Quantize(linearVelocity, -MaxVel, MaxVel, 12);
|
||||
|
||||
bool fixedRotation = msg.ReadBoolean();
|
||||
float? rotation = null;
|
||||
float? angularVelocity = null;
|
||||
if (!fixedRotation)
|
||||
{
|
||||
rotation = msg.ReadSingle();
|
||||
float MaxAngularVel = NetConfig.MaxPhysicsBodyAngularVelocity;
|
||||
angularVelocity = msg.ReadRangedSingle(-MaxAngularVel, MaxAngularVel, 8);
|
||||
angularVelocity = NetConfig.Quantize(angularVelocity.Value, -MaxAngularVel, MaxAngularVel, 8);
|
||||
}
|
||||
|
||||
bool readStatus = msg.ReadBoolean();
|
||||
if (readStatus)
|
||||
{
|
||||
ReadStatus(msg);
|
||||
AIController?.ClientRead(msg);
|
||||
}
|
||||
|
||||
msg.ReadPadBits();
|
||||
|
||||
int index = 0;
|
||||
if (GameMain.Client.Character == this && CanMove)
|
||||
{
|
||||
var posInfo = new CharacterStateInfo(
|
||||
pos, rotation,
|
||||
networkUpdateID,
|
||||
facingRight ? Direction.Right : Direction.Left,
|
||||
selectedCharacter, selectedItem, animation);
|
||||
|
||||
while (index < memState.Count && NetIdUtils.IdMoreRecent(posInfo.ID, memState[index].ID))
|
||||
index++;
|
||||
memState.Insert(index, posInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
var posInfo = new CharacterStateInfo(
|
||||
pos, rotation,
|
||||
linearVelocity, angularVelocity,
|
||||
sendingTime, facingRight ? Direction.Right : Direction.Left,
|
||||
selectedCharacter, selectedItem, animation);
|
||||
|
||||
while (index < memState.Count && posInfo.Timestamp > memState[index].Timestamp)
|
||||
index++;
|
||||
memState.Insert(index, posInfo);
|
||||
}
|
||||
|
||||
break;
|
||||
case ServerNetObject.ENTITY_EVENT:
|
||||
int eventType = msg.ReadRangedInteger(0, 13);
|
||||
switch (eventType)
|
||||
{
|
||||
case 0: //NetEntityEvent.Type.InventoryState
|
||||
if (Inventory == null)
|
||||
{
|
||||
string errorMsg = "Received an inventory update message for an entity with no inventory ([name], removed: " + Removed + ")";
|
||||
DebugConsole.ThrowError(errorMsg.Replace("[name]", Name));
|
||||
GameAnalyticsManager.AddErrorEventOnce("CharacterNetworking.ClientRead:NoInventory" + ID, GameAnalyticsManager.ErrorSeverity.Error, errorMsg.Replace("[name]", SpeciesName));
|
||||
|
||||
//read anyway to prevent messing up reading the rest of the message
|
||||
_ = msg.ReadUInt16();
|
||||
byte inventoryItemCount = msg.ReadByte();
|
||||
for (int i = 0; i < inventoryItemCount; i++)
|
||||
{
|
||||
msg.ReadUInt16();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Inventory.ClientRead(type, msg, sendingTime);
|
||||
}
|
||||
break;
|
||||
case 1: //NetEntityEvent.Type.Control
|
||||
bool myCharacter = msg.ReadBoolean();
|
||||
byte ownerID = msg.ReadByte();
|
||||
ResetNetState();
|
||||
if (myCharacter)
|
||||
{
|
||||
if (controlled != null)
|
||||
{
|
||||
LastNetworkUpdateID = controlled.LastNetworkUpdateID;
|
||||
}
|
||||
|
||||
if (!IsDead) { Controlled = this; }
|
||||
IsRemotePlayer = false;
|
||||
GameMain.Client.HasSpawned = true;
|
||||
GameMain.Client.Character = this;
|
||||
GameMain.LightManager.LosEnabled = true;
|
||||
GameMain.LightManager.LosAlpha = 1f;
|
||||
GameMain.Client.WaitForNextRoundRespawn = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (controlled == this)
|
||||
{
|
||||
Controlled = null;
|
||||
IsRemotePlayer = ownerID > 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2: //NetEntityEvent.Type.Status
|
||||
ReadStatus(msg);
|
||||
break;
|
||||
case 3: //NetEntityEvent.Type.UpdateSkills
|
||||
int skillCount = msg.ReadByte();
|
||||
for (int i = 0; i < skillCount; i++)
|
||||
{
|
||||
string skillIdentifier = msg.ReadString();
|
||||
float skillLevel = msg.ReadSingle();
|
||||
info?.SetSkillLevel(skillIdentifier, skillLevel);
|
||||
}
|
||||
break;
|
||||
case 4: // NetEntityEvent.Type.SetAttackTarget
|
||||
case 5: //NetEntityEvent.Type.ExecuteAttack
|
||||
int attackLimbIndex = msg.ReadByte();
|
||||
UInt16 targetEntityID = msg.ReadUInt16();
|
||||
int targetLimbIndex = msg.ReadByte();
|
||||
Vector2 targetSimPos = new Vector2(msg.ReadSingle(), msg.ReadSingle());
|
||||
//255 = entity already removed, no need to do anything
|
||||
if (attackLimbIndex == 255 || Removed) { break; }
|
||||
if (attackLimbIndex >= AnimController.Limbs.Length)
|
||||
{
|
||||
DebugConsole.ThrowError($"Received invalid {(eventType == 4 ? "SetAttackTarget" : "ExecuteAttack")} message. Limb index out of bounds (character: {Name}, limb index: {attackLimbIndex}, limb count: {AnimController.Limbs.Length})");
|
||||
break;
|
||||
}
|
||||
Limb attackLimb = AnimController.Limbs[attackLimbIndex];
|
||||
Limb targetLimb = null;
|
||||
IDamageable targetEntity = FindEntityByID(targetEntityID) as IDamageable;
|
||||
if (targetEntity == null && eventType == 4)
|
||||
{
|
||||
DebugConsole.ThrowError($"Received invalid SetAttackTarget message. Target entity not found (ID {targetEntityID})");
|
||||
break;
|
||||
}
|
||||
if (targetEntity is Character targetCharacter)
|
||||
{
|
||||
if (targetLimbIndex >= targetCharacter.AnimController.Limbs.Length)
|
||||
{
|
||||
DebugConsole.ThrowError($"Received invalid {(eventType == 4 ? "SetAttackTarget" : "ExecuteAttack")} message. Target limb index out of bounds (target character: {targetCharacter.Name}, limb index: {targetLimbIndex}, limb count: {targetCharacter.AnimController.Limbs.Length})");
|
||||
break;
|
||||
}
|
||||
targetLimb = targetCharacter.AnimController.Limbs[targetLimbIndex];
|
||||
}
|
||||
if (attackLimb?.attack != null && Controlled != this)
|
||||
{
|
||||
if (eventType == 4)
|
||||
{
|
||||
SetAttackTarget(attackLimb, targetEntity, targetSimPos);
|
||||
PlaySound(CharacterSound.SoundType.Attack, maxInterval: 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
attackLimb.ExecuteAttack(targetEntity, targetLimb, out _);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 6: //NetEntityEvent.Type.AssignCampaignInteraction
|
||||
byte campaignInteractionType = msg.ReadByte();
|
||||
bool requireConsciousness = msg.ReadBoolean();
|
||||
(GameMain.GameSession?.GameMode as CampaignMode)?.AssignNPCMenuInteraction(this, (CampaignMode.InteractionType)campaignInteractionType);
|
||||
RequireConsciousnessForCustomInteract = requireConsciousness;
|
||||
break;
|
||||
case 7: //NetEntityEvent.Type.ObjectiveManagerState
|
||||
// 1 = order, 2 = objective
|
||||
int msgType = msg.ReadRangedInteger(0, 2);
|
||||
if (msgType == 0) { break; }
|
||||
bool validData = msg.ReadBoolean();
|
||||
if (!validData) { break; }
|
||||
if (msgType == 1)
|
||||
{
|
||||
int orderIndex = msg.ReadRangedInteger(0, Order.PrefabList.Count);
|
||||
var orderPrefab = Order.PrefabList[orderIndex];
|
||||
string option = null;
|
||||
if (orderPrefab.HasOptions)
|
||||
{
|
||||
int optionIndex = msg.ReadRangedInteger(-1, orderPrefab.AllOptions.Length);
|
||||
if (optionIndex > -1)
|
||||
{
|
||||
option = orderPrefab.AllOptions[optionIndex];
|
||||
}
|
||||
}
|
||||
GameMain.GameSession?.CrewManager?.SetOrderHighlight(this, orderPrefab.Identifier, option);
|
||||
}
|
||||
else if (msgType == 2)
|
||||
{
|
||||
string identifier = msg.ReadString();
|
||||
string option = msg.ReadString();
|
||||
ushort objectiveTargetEntityId = msg.ReadUInt16();
|
||||
var objectiveTargetEntity = FindEntityByID(objectiveTargetEntityId);
|
||||
GameMain.GameSession?.CrewManager?.CreateObjectiveIcon(this, identifier, option, objectiveTargetEntity);
|
||||
}
|
||||
break;
|
||||
case 8: //NetEntityEvent.Type.TeamChange
|
||||
byte newTeamId = msg.ReadByte();
|
||||
ChangeTeam((CharacterTeamType)newTeamId);
|
||||
break;
|
||||
case 9: //NetEntityEvent.Type.AddToCrew
|
||||
GameMain.GameSession.CrewManager.AddCharacter(this);
|
||||
CharacterTeamType teamID = (CharacterTeamType)msg.ReadByte();
|
||||
ushort itemCount = msg.ReadUInt16();
|
||||
for (int i = 0; i < itemCount; i++)
|
||||
{
|
||||
ushort itemID = msg.ReadUInt16();
|
||||
if (!(Entity.FindEntityByID(itemID) is Item item)) { continue; }
|
||||
item.AllowStealing = true;
|
||||
var wifiComponent = item.GetComponent<WifiComponent>();
|
||||
if (wifiComponent != null)
|
||||
{
|
||||
wifiComponent.TeamID = teamID;
|
||||
}
|
||||
var idCard = item.GetComponent<IdCard>();
|
||||
if (idCard != null)
|
||||
{
|
||||
idCard.TeamID = teamID;
|
||||
idCard.SubmarineSpecificID = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 10: //NetEntityEvent.Type.UpdateExperience
|
||||
int experienceAmount = msg.ReadInt32();
|
||||
info?.SetExperience(experienceAmount);
|
||||
break;
|
||||
case 11: //NetEntityEvent.Type.UpdateTalents:
|
||||
ushort talentCount = msg.ReadUInt16();
|
||||
for (int i = 0; i < talentCount; i++)
|
||||
{
|
||||
bool addedThisRound = msg.ReadBoolean();
|
||||
UInt32 talentIdentifier = msg.ReadUInt32();
|
||||
GiveTalent(talentIdentifier, addedThisRound);
|
||||
}
|
||||
break;
|
||||
case 12: //NetEntityEvent.Type.UpdateMoney:
|
||||
int moneyAmount = msg.ReadInt32();
|
||||
SetMoney(moneyAmount);
|
||||
break;
|
||||
case 13: //NetEntityEvent.Type.UpdatePermanentStats:
|
||||
byte savedStatValueCount = msg.ReadByte();
|
||||
StatTypes statType = (StatTypes)msg.ReadByte();
|
||||
info?.ClearSavedStatValues(statType);
|
||||
for (int i = 0; i < savedStatValueCount; i++)
|
||||
{
|
||||
string statIdentifier = msg.ReadString();
|
||||
float statValue = msg.ReadSingle();
|
||||
bool removeOnDeath = msg.ReadBoolean();
|
||||
info?.ChangeSavedStatValue(statType, statValue, statIdentifier, removeOnDeath, setValue: true);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
msg.ReadPadBits();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Vector2 pos = new Vector2(
|
||||
msg.ReadSingle(),
|
||||
msg.ReadSingle());
|
||||
float MaxVel = NetConfig.MaxPhysicsBodyVelocity;
|
||||
Vector2 linearVelocity = new Vector2(
|
||||
msg.ReadRangedSingle(-MaxVel, MaxVel, 12),
|
||||
msg.ReadRangedSingle(-MaxVel, MaxVel, 12));
|
||||
linearVelocity = NetConfig.Quantize(linearVelocity, -MaxVel, MaxVel, 12);
|
||||
|
||||
bool fixedRotation = msg.ReadBoolean();
|
||||
float? rotation = null;
|
||||
float? angularVelocity = null;
|
||||
if (!fixedRotation)
|
||||
{
|
||||
rotation = msg.ReadSingle();
|
||||
float MaxAngularVel = NetConfig.MaxPhysicsBodyAngularVelocity;
|
||||
angularVelocity = msg.ReadRangedSingle(-MaxAngularVel, MaxAngularVel, 8);
|
||||
angularVelocity = NetConfig.Quantize(angularVelocity.Value, -MaxAngularVel, MaxAngularVel, 8);
|
||||
}
|
||||
|
||||
bool readStatus = msg.ReadBoolean();
|
||||
if (readStatus)
|
||||
{
|
||||
ReadStatus(msg);
|
||||
AIController?.ClientRead(msg);
|
||||
}
|
||||
|
||||
msg.ReadPadBits();
|
||||
|
||||
int index = 0;
|
||||
if (GameMain.Client.Character == this && CanMove)
|
||||
{
|
||||
var posInfo = new CharacterStateInfo(
|
||||
pos, rotation,
|
||||
networkUpdateID,
|
||||
facingRight ? Direction.Right : Direction.Left,
|
||||
selectedCharacter, selectedItem, animation);
|
||||
|
||||
while (index < memState.Count && NetIdUtils.IdMoreRecent(posInfo.ID, memState[index].ID))
|
||||
index++;
|
||||
memState.Insert(index, posInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
var posInfo = new CharacterStateInfo(
|
||||
pos, rotation,
|
||||
linearVelocity, angularVelocity,
|
||||
sendingTime, facingRight ? Direction.Right : Direction.Left,
|
||||
selectedCharacter, selectedItem, animation);
|
||||
|
||||
while (index < memState.Count && posInfo.Timestamp > memState[index].Timestamp)
|
||||
index++;
|
||||
memState.Insert(index, posInfo);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||
{
|
||||
EventType eventType = (EventType)msg.ReadRangedInteger((int)EventType.MinValue, (int)EventType.MaxValue);
|
||||
switch (eventType)
|
||||
{
|
||||
case EventType.InventoryState:
|
||||
if (Inventory == null)
|
||||
{
|
||||
string errorMsg = "Received an inventory update message for an entity with no inventory ([name], removed: " + Removed + ")";
|
||||
DebugConsole.ThrowError(errorMsg.Replace("[name]", Name));
|
||||
GameAnalyticsManager.AddErrorEventOnce("CharacterNetworking.ClientRead:NoInventory" + ID, GameAnalyticsManager.ErrorSeverity.Error, errorMsg.Replace("[name]", SpeciesName.Value));
|
||||
|
||||
//read anyway to prevent messing up reading the rest of the message
|
||||
_ = msg.ReadUInt16();
|
||||
byte inventoryItemCount = msg.ReadByte();
|
||||
for (int i = 0; i < inventoryItemCount; i++)
|
||||
{
|
||||
msg.ReadUInt16();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Inventory.ClientEventRead(msg, sendingTime);
|
||||
}
|
||||
break;
|
||||
case EventType.Control:
|
||||
bool myCharacter = msg.ReadBoolean();
|
||||
byte ownerID = msg.ReadByte();
|
||||
ResetNetState();
|
||||
if (myCharacter)
|
||||
{
|
||||
if (controlled != null)
|
||||
{
|
||||
LastNetworkUpdateID = controlled.LastNetworkUpdateID;
|
||||
}
|
||||
|
||||
if (!IsDead) { Controlled = this; }
|
||||
IsRemotePlayer = false;
|
||||
GameMain.Client.HasSpawned = true;
|
||||
GameMain.Client.Character = this;
|
||||
GameMain.LightManager.LosEnabled = true;
|
||||
GameMain.LightManager.LosAlpha = 1f;
|
||||
GameMain.Client.WaitForNextRoundRespawn = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (controlled == this)
|
||||
{
|
||||
Controlled = null;
|
||||
}
|
||||
if (GameMain.Client?.Character == this)
|
||||
{
|
||||
GameMain.Client.Character = null;
|
||||
}
|
||||
IsRemotePlayer = ownerID > 0;
|
||||
}
|
||||
break;
|
||||
case EventType.Status:
|
||||
ReadStatus(msg);
|
||||
break;
|
||||
case EventType.UpdateSkills:
|
||||
int skillCount = msg.ReadByte();
|
||||
for (int i = 0; i < skillCount; i++)
|
||||
{
|
||||
Identifier skillIdentifier = msg.ReadIdentifier();
|
||||
float skillLevel = msg.ReadSingle();
|
||||
info?.SetSkillLevel(skillIdentifier, skillLevel);
|
||||
}
|
||||
break;
|
||||
case EventType.SetAttackTarget:
|
||||
case EventType.ExecuteAttack:
|
||||
int attackLimbIndex = msg.ReadByte();
|
||||
UInt16 targetEntityID = msg.ReadUInt16();
|
||||
int targetLimbIndex = msg.ReadByte();
|
||||
float targetX = msg.ReadSingle();
|
||||
float targetY = msg.ReadSingle();
|
||||
Vector2 targetSimPos = new Vector2(targetX, targetY);
|
||||
//255 = entity already removed, no need to do anything
|
||||
if (attackLimbIndex == 255 || Removed) { break; }
|
||||
if (attackLimbIndex >= AnimController.Limbs.Length)
|
||||
{
|
||||
string errorMsg = $"Received invalid {(eventType == EventType.SetAttackTarget ? "SetAttackTarget" : "ExecuteAttack")} message. Limb index out of bounds (character: {Name}, limb index: {attackLimbIndex}, limb count: {AnimController.Limbs.Length})";
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("Character.ClientEventRead:AttackLimbOutOfBounds", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
break;
|
||||
}
|
||||
Limb attackLimb = AnimController.Limbs[attackLimbIndex];
|
||||
Limb targetLimb = null;
|
||||
IDamageable targetEntity = FindEntityByID(targetEntityID) as IDamageable;
|
||||
if (targetEntity == null && eventType == EventType.SetAttackTarget)
|
||||
{
|
||||
DebugConsole.ThrowError($"Received invalid SetAttackTarget message. Target entity not found (ID {targetEntityID})");
|
||||
GameAnalyticsManager.AddErrorEventOnce("Character.ClientEventRead:TargetNotFound", GameAnalyticsManager.ErrorSeverity.Error, "Received invalid SetAttackTarget message. Target entity not found.");
|
||||
break;
|
||||
}
|
||||
if (targetEntity is Character targetCharacter && targetLimbIndex != 255)
|
||||
{
|
||||
if (targetLimbIndex >= targetCharacter.AnimController.Limbs.Length)
|
||||
{
|
||||
DebugConsole.ThrowError($"Received invalid {(eventType == EventType.SetAttackTarget ? "SetAttackTarget" : "ExecuteAttack")} message. Target limb index out of bounds (target character: {targetCharacter.Name}, limb index: {targetLimbIndex}, limb count: {targetCharacter.AnimController.Limbs.Length})");
|
||||
string errorMsgWithoutName = $"Received invalid {(eventType == EventType.SetAttackTarget ? "SetAttackTarget" : "ExecuteAttack")} message. Target limb index out of bounds (target character: {targetCharacter.SpeciesName}, limb index: {targetLimbIndex}, limb count: {targetCharacter.AnimController.Limbs.Length})";
|
||||
GameAnalyticsManager.AddErrorEventOnce("Character.ClientEventRead:TargetLimbOutOfBounds", GameAnalyticsManager.ErrorSeverity.Error, errorMsgWithoutName);
|
||||
break;
|
||||
}
|
||||
targetLimb = targetCharacter.AnimController.Limbs[targetLimbIndex];
|
||||
}
|
||||
if (attackLimb?.attack != null && Controlled != this)
|
||||
{
|
||||
if (eventType == EventType.SetAttackTarget)
|
||||
{
|
||||
SetAttackTarget(attackLimb, targetEntity, targetSimPos);
|
||||
PlaySound(CharacterSound.SoundType.Attack, maxInterval: 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
attackLimb.ExecuteAttack(targetEntity, targetLimb, out _);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EventType.AssignCampaignInteraction:
|
||||
byte campaignInteractionType = msg.ReadByte();
|
||||
bool requireConsciousness = msg.ReadBoolean();
|
||||
(GameMain.GameSession?.GameMode as CampaignMode)?.AssignNPCMenuInteraction(this, (CampaignMode.InteractionType)campaignInteractionType);
|
||||
RequireConsciousnessForCustomInteract = requireConsciousness;
|
||||
break;
|
||||
case EventType.ObjectiveManagerState:
|
||||
// 1 = order, 2 = objective
|
||||
AIObjectiveManager.ObjectiveType msgType
|
||||
= (AIObjectiveManager.ObjectiveType)msg.ReadRangedInteger(
|
||||
(int)AIObjectiveManager.ObjectiveType.MinValue,
|
||||
(int)AIObjectiveManager.ObjectiveType.MaxValue);
|
||||
if (msgType == 0) { break; }
|
||||
bool validData = msg.ReadBoolean();
|
||||
if (!validData) { break; }
|
||||
if (msgType == AIObjectiveManager.ObjectiveType.Order)
|
||||
{
|
||||
UInt32 orderPrefabUintIdentifier = msg.ReadUInt32();
|
||||
var orderPrefab = OrderPrefab.Prefabs.Find(p => p.UintIdentifier == orderPrefabUintIdentifier);
|
||||
Identifier option = Identifier.Empty;
|
||||
if (orderPrefab.HasOptions)
|
||||
{
|
||||
int optionIndex = msg.ReadRangedInteger(-1, orderPrefab.AllOptions.Length);
|
||||
if (optionIndex > -1)
|
||||
{
|
||||
option = orderPrefab.AllOptions[optionIndex];
|
||||
}
|
||||
}
|
||||
GameMain.GameSession?.CrewManager?.SetOrderHighlight(this, orderPrefab.Identifier, option);
|
||||
}
|
||||
else if (msgType == AIObjectiveManager.ObjectiveType.Objective)
|
||||
{
|
||||
Identifier identifier = msg.ReadIdentifier();
|
||||
Identifier option = msg.ReadIdentifier();
|
||||
ushort objectiveTargetEntityId = msg.ReadUInt16();
|
||||
var objectiveTargetEntity = FindEntityByID(objectiveTargetEntityId);
|
||||
GameMain.GameSession?.CrewManager?.CreateObjectiveIcon(this, identifier, option, objectiveTargetEntity);
|
||||
}
|
||||
break;
|
||||
case EventType.TeamChange:
|
||||
byte newTeamId = msg.ReadByte();
|
||||
ChangeTeam((CharacterTeamType)newTeamId);
|
||||
break;
|
||||
case EventType.AddToCrew:
|
||||
GameMain.GameSession.CrewManager.AddCharacter(this);
|
||||
CharacterTeamType teamID = (CharacterTeamType)msg.ReadByte();
|
||||
ushort itemCount = msg.ReadUInt16();
|
||||
for (int i = 0; i < itemCount; i++)
|
||||
{
|
||||
ushort itemID = msg.ReadUInt16();
|
||||
if (!(Entity.FindEntityByID(itemID) is Item item)) { continue; }
|
||||
item.AllowStealing = true;
|
||||
var wifiComponent = item.GetComponent<WifiComponent>();
|
||||
if (wifiComponent != null)
|
||||
{
|
||||
wifiComponent.TeamID = teamID;
|
||||
}
|
||||
var idCard = item.GetComponent<IdCard>();
|
||||
if (idCard != null)
|
||||
{
|
||||
idCard.TeamID = teamID;
|
||||
idCard.SubmarineSpecificID = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EventType.UpdateExperience:
|
||||
int experienceAmount = msg.ReadInt32();
|
||||
info?.SetExperience(experienceAmount);
|
||||
break;
|
||||
case EventType.UpdateTalents:
|
||||
ushort talentCount = msg.ReadUInt16();
|
||||
for (int i = 0; i < talentCount; i++)
|
||||
{
|
||||
bool addedThisRound = msg.ReadBoolean();
|
||||
UInt32 talentIdentifier = msg.ReadUInt32();
|
||||
GiveTalent(talentIdentifier, addedThisRound);
|
||||
}
|
||||
break;
|
||||
case EventType.UpdateMoney:
|
||||
int moneyAmount = msg.ReadInt32();
|
||||
SetMoney(moneyAmount);
|
||||
break;
|
||||
case EventType.UpdatePermanentStats:
|
||||
byte savedStatValueCount = msg.ReadByte();
|
||||
StatTypes statType = (StatTypes)msg.ReadByte();
|
||||
info?.ClearSavedStatValues(statType);
|
||||
for (int i = 0; i < savedStatValueCount; i++)
|
||||
{
|
||||
string statIdentifier = msg.ReadString();
|
||||
float statValue = msg.ReadSingle();
|
||||
bool removeOnDeath = msg.ReadBoolean();
|
||||
info?.ChangeSavedStatValue(statType, statValue, statIdentifier, removeOnDeath, setValue: true);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
msg.ReadPadBits();
|
||||
}
|
||||
|
||||
public static Character ReadSpawnData(IReadMessage inc)
|
||||
@@ -542,9 +551,11 @@ namespace Barotrauma
|
||||
{
|
||||
bool hasOwner = inc.ReadBoolean();
|
||||
int ownerId = hasOwner ? inc.ReadByte() : -1;
|
||||
int balance = hasOwner ? inc.ReadInt32() : -1;
|
||||
int rewardDistribution = hasOwner ? inc.ReadRangedInteger(0, 100) : -1;
|
||||
byte teamID = inc.ReadByte();
|
||||
bool hasAi = inc.ReadBoolean();
|
||||
string infoSpeciesName = inc.ReadString();
|
||||
Identifier infoSpeciesName = inc.ReadIdentifier();
|
||||
|
||||
CharacterInfo info = CharacterInfo.ClientRead(infoSpeciesName, inc);
|
||||
try
|
||||
@@ -558,6 +569,12 @@ namespace Barotrauma
|
||||
}
|
||||
character.TeamID = (CharacterTeamType)teamID;
|
||||
character.CampaignInteractionType = (CampaignMode.InteractionType)inc.ReadByte();
|
||||
if (character.CampaignInteractionType == CampaignMode.InteractionType.Store)
|
||||
{
|
||||
character.MerchantIdentifier = inc.ReadIdentifier();
|
||||
}
|
||||
character.Wallet.Balance = balance;
|
||||
character.Wallet.RewardDistribution = rewardDistribution;
|
||||
if (character.CampaignInteractionType != CampaignMode.InteractionType.None)
|
||||
{
|
||||
(GameMain.GameSession.GameMode as CampaignMode)?.AssignNPCMenuInteraction(character, character.CampaignInteractionType);
|
||||
@@ -567,7 +584,7 @@ namespace Barotrauma
|
||||
int orderCount = inc.ReadByte();
|
||||
for (int i = 0; i < orderCount; i++)
|
||||
{
|
||||
int orderPrefabIndex = inc.ReadByte();
|
||||
UInt32 orderPrefabUintIdentifier = inc.ReadUInt32();
|
||||
Entity targetEntity = FindEntityByID(inc.ReadUInt16());
|
||||
Character orderGiver = inc.ReadBoolean() ? FindEntityByID(inc.ReadUInt16()) as Character : null;
|
||||
int orderOptionIndex = inc.ReadByte();
|
||||
@@ -581,18 +598,23 @@ namespace Barotrauma
|
||||
targetPosition = new OrderTarget(new Vector2(x, y), hull, creatingFromExistingData: true);
|
||||
}
|
||||
|
||||
if (orderPrefabIndex >= 0 && orderPrefabIndex < Order.PrefabList.Count)
|
||||
OrderPrefab orderPrefab =
|
||||
OrderPrefab.Prefabs.Find(p => p.UintIdentifier == orderPrefabUintIdentifier);
|
||||
if (orderPrefab != null)
|
||||
{
|
||||
var orderPrefab = Order.PrefabList[orderPrefabIndex];
|
||||
var component = orderPrefab.GetTargetItemComponent(targetEntity as Item);
|
||||
if (!orderPrefab.MustSetTarget || (targetEntity != null && component != null) || targetPosition != null)
|
||||
{
|
||||
var order = targetPosition == null ?
|
||||
new Order(orderPrefab, targetEntity, component, orderGiver: orderGiver) :
|
||||
new Order(orderPrefab, targetPosition, orderGiver: orderGiver);
|
||||
character.SetOrder(order,
|
||||
orderOptionIndex >= 0 && orderOptionIndex < orderPrefab.Options.Length ? orderPrefab.Options[orderOptionIndex] : null,
|
||||
orderPriority, orderGiver, speak: false, force: true);
|
||||
order = order.WithOption(
|
||||
orderOptionIndex >= 0 && orderOptionIndex < orderPrefab.Options.Length
|
||||
? orderPrefab.Options[orderOptionIndex]
|
||||
: Identifier.Empty)
|
||||
.WithManualPriority(orderPriority)
|
||||
.WithOrderGiver(orderGiver);
|
||||
character.SetOrder(order, isNewOrder: true, speak: false, force: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -601,7 +623,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError("Invalid order prefab index - index (" + orderPrefabIndex + ") out of bounds.");
|
||||
DebugConsole.ThrowError("Invalid order prefab index - index (" + orderPrefabUintIdentifier + ") out of bounds.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Barotrauma.Sounds;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -13,20 +14,17 @@ namespace Barotrauma
|
||||
public readonly CharacterParams.SoundParams Params;
|
||||
|
||||
public SoundType Type => Params.State;
|
||||
public Gender Gender => Params.Gender;
|
||||
public ImmutableHashSet<Identifier> TagSet => Params.TagSet;
|
||||
public float Volume => roundSound == null ? 0.0f : roundSound.Volume;
|
||||
public float Range => roundSound == null ? 0.0f : roundSound.Range;
|
||||
public Sound Sound => roundSound?.Sound;
|
||||
|
||||
public bool IgnoreMuffling
|
||||
{
|
||||
get { return roundSound?.IgnoreMuffling ?? false; }
|
||||
}
|
||||
public bool IgnoreMuffling => roundSound?.IgnoreMuffling ?? false;
|
||||
|
||||
public CharacterSound(CharacterParams.SoundParams soundParams)
|
||||
{
|
||||
Params = soundParams;
|
||||
roundSound = Submarine.LoadRoundSound(soundParams.Element);
|
||||
roundSound = RoundSound.Load(soundParams.Element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Barotrauma
|
||||
public Vector2 Size;
|
||||
|
||||
private readonly Submarine parentSub;
|
||||
public string Text
|
||||
public LocalizedString Text
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
@@ -58,7 +58,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
public HUDProgressBar(Vector2 worldPosition, string textTag, Submarine parentSubmarine = null)
|
||||
: this(worldPosition, parentSubmarine, GUI.Style.Red, GUI.Style.Green, textTag)
|
||||
: this(worldPosition, parentSubmarine, GUIStyle.Red, GUIStyle.Green, textTag)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace Barotrauma
|
||||
if (!string.IsNullOrEmpty(textTag))
|
||||
{
|
||||
this.textTag = textTag;
|
||||
Text = TextManager.Get(textTag);
|
||||
Text = TextManager.Get(textTag).Fallback(textTag);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,12 +101,12 @@ namespace Barotrauma
|
||||
color * a,
|
||||
Color.White * a * 0.8f);
|
||||
|
||||
if (!string.IsNullOrEmpty(Text))
|
||||
if (!Text.IsNullOrEmpty())
|
||||
{
|
||||
Vector2 textSize = GUI.SmallFont.MeasureString(Text);
|
||||
Vector2 textSize = GUIStyle.SmallFont.MeasureString(Text);
|
||||
Vector2 textPos = new Vector2(pos.X + (Size.X - textSize.X) / 2, pos.Y - textSize.Y * 1.2f);
|
||||
GUI.DrawString(spriteBatch, textPos - Vector2.One, Text, Color.Black * a, font: GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, textPos, Text, Color.White * a, font: GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, textPos - Vector2.One, Text, Color.Black * a, font: GUIStyle.SmallFont);
|
||||
GUI.DrawString(spriteBatch, textPos, Text, Color.White * a, font: GUIStyle.SmallFont);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class AfflictionHusk : Affliction
|
||||
{
|
||||
private InfectionState? prevDisplayedMessage;
|
||||
partial void UpdateMessages()
|
||||
{
|
||||
if (character != Character.Controlled) { return; }
|
||||
if (Prefab is AfflictionPrefabHusk { SendMessages: false }) { return; }
|
||||
if (prevDisplayedMessage.HasValue && prevDisplayedMessage.Value == State) { return; }
|
||||
|
||||
switch (State)
|
||||
{
|
||||
case InfectionState.Dormant:
|
||||
if (Strength < DormantThreshold * 0.5f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
GUI.AddMessage(TextManager.Get("HuskDormant"), GUI.Style.Red);
|
||||
break;
|
||||
case InfectionState.Transition:
|
||||
GUI.AddMessage(TextManager.Get("HuskCantSpeak"), GUI.Style.Red);
|
||||
break;
|
||||
case InfectionState.Active:
|
||||
if (character.Params.UseHuskAppendage)
|
||||
{
|
||||
GUI.AddMessage(TextManager.GetWithVariable("HuskActivate", "[Attack]", GameMain.Config.KeyBindText(InputType.Attack)), GUI.Style.Red);
|
||||
}
|
||||
break;
|
||||
case InfectionState.Final:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
prevDisplayedMessage = State;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,7 +75,7 @@ namespace Barotrauma
|
||||
case FloodType.Minor:
|
||||
currentFloodState += deltaTime;
|
||||
//lerp the water surface in all hulls 15 units above the floor within 10 seconds
|
||||
foreach (Hull hull in Hull.hullList)
|
||||
foreach (Hull hull in Hull.HullList)
|
||||
{
|
||||
for (int i = hull.FakeFireSources.Count - 1; i >= 0; i--)
|
||||
{
|
||||
@@ -87,7 +87,7 @@ namespace Barotrauma
|
||||
case FloodType.Major:
|
||||
currentFloodState += deltaTime;
|
||||
//create a full flood in 10 seconds
|
||||
foreach (Hull hull in Hull.hullList)
|
||||
foreach (Hull hull in Hull.HullList)
|
||||
{
|
||||
for (int i = hull.FakeFireSources.Count - 1; i >= 0; i--)
|
||||
{
|
||||
@@ -98,7 +98,7 @@ namespace Barotrauma
|
||||
break;
|
||||
case FloodType.HideFlooding:
|
||||
//hide water inside hulls (the player can't see which hulls are flooded)
|
||||
foreach (Hull hull in Hull.hullList)
|
||||
foreach (Hull hull in Hull.HullList)
|
||||
{
|
||||
hull.DrawSurface = hull.Rect.Y - hull.Rect.Height;
|
||||
}
|
||||
@@ -140,7 +140,7 @@ namespace Barotrauma
|
||||
character.Submarine != null &&
|
||||
createFireSourceTimer > MathHelper.Lerp(MaxFakeFireSourceInterval, MinFakeFireSourceInterval, Strength / 100.0f))
|
||||
{
|
||||
Hull fireHull = Hull.hullList.GetRandom(h => h.Submarine == character.Submarine);
|
||||
Hull fireHull = Hull.HullList.GetRandomUnsynced(h => h.Submarine == character.Submarine);
|
||||
if (fireHull != null)
|
||||
{
|
||||
var fakeFire = new DummyFireSource(Vector2.One * 500.0f, new Vector2(Rand.Range(fireHull.WorldRect.X, fireHull.WorldRect.Right), fireHull.WorldPosition.Y + 1), fireHull, isNetworkMessage: true)
|
||||
|
||||
@@ -14,11 +14,31 @@ namespace Barotrauma
|
||||
{
|
||||
private static bool toggledThisFrame;
|
||||
|
||||
public static Sprite DamageOverlay;
|
||||
public class DamageOverlayPrefab : Prefab
|
||||
{
|
||||
public readonly static PrefabSelector<DamageOverlayPrefab> Prefabs = new PrefabSelector<DamageOverlayPrefab>();
|
||||
|
||||
public static string DamageOverlayFile;
|
||||
public readonly Sprite DamageOverlay;
|
||||
|
||||
private static string[] strengthTexts;
|
||||
public DamageOverlayPrefab(ContentXElement element, AfflictionsFile file) : base(file, file.Path.Value.ToIdentifier())
|
||||
{
|
||||
DamageOverlay = new Sprite(element);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
DamageOverlay.Remove();
|
||||
}
|
||||
}
|
||||
|
||||
public static Sprite DamageOverlay => DamageOverlayPrefab.Prefabs.ActivePrefab.DamageOverlay;
|
||||
|
||||
private readonly static LocalizedString[] strengthTexts = new LocalizedString[]
|
||||
{
|
||||
TextManager.Get("AfflictionStrengthLow"),
|
||||
TextManager.Get("AfflictionStrengthMedium"),
|
||||
TextManager.Get("AfflictionStrengthHigh")
|
||||
};
|
||||
|
||||
private Point screenResolution;
|
||||
|
||||
@@ -134,7 +154,7 @@ namespace Barotrauma
|
||||
Character.Controlled.ResetInteract = true;
|
||||
if (openHealthWindow != null)
|
||||
{
|
||||
if (value.Character.Info == null || value.Character == Character.Controlled || Character.Controlled.HasEquippedItem("healthscanner"))
|
||||
if (value.Character.Info == null || value.Character == Character.Controlled || Character.Controlled.HasEquippedItem("healthscanner".ToIdentifier()))
|
||||
{
|
||||
openHealthWindow.characterName.Text = value.Character.Name;
|
||||
}
|
||||
@@ -173,20 +193,10 @@ namespace Barotrauma
|
||||
|
||||
private GUIFrame healthBarHolder;
|
||||
|
||||
partial void InitProjSpecific(XElement element, Character character)
|
||||
partial void InitProjSpecific(ContentXElement element, Character character)
|
||||
{
|
||||
DisplayedVitality = MaxVitality;
|
||||
|
||||
if (strengthTexts == null)
|
||||
{
|
||||
strengthTexts = new string[]
|
||||
{
|
||||
TextManager.Get("AfflictionStrengthLow"),
|
||||
TextManager.Get("AfflictionStrengthMedium"),
|
||||
TextManager.Get("AfflictionStrengthHigh")
|
||||
};
|
||||
}
|
||||
|
||||
character.OnAttacked += OnAttacked;
|
||||
|
||||
healthWindow = new GUIFrame(new RectTransform(new Vector2(0.35f, 0.6f), GUI.Canvas, anchor: Anchor.Center, scaleBasis: ScaleBasis.Smallest), style: "GUIFrameListBox");
|
||||
@@ -200,13 +210,13 @@ namespace Barotrauma
|
||||
{
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
|
||||
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, character != Character.Controlled);
|
||||
});
|
||||
characterName = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), nameContainer.RectTransform), "", textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont)
|
||||
characterName = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), nameContainer.RectTransform), "", textAlignment: Alignment.CenterLeft, font: GUIStyle.SubHeadingFont)
|
||||
{
|
||||
AutoScaleHorizontal = true
|
||||
};
|
||||
@@ -220,12 +230,12 @@ namespace Barotrauma
|
||||
var healthBarContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.07f), healthWindowVerticalLayout.RectTransform), style: null);
|
||||
var healthBarIcon = new GUIFrame(new RectTransform(new Vector2(0.095f, 1.0f), healthBarContainer.RectTransform), style: "GUIHealthBarIcon");
|
||||
healthWindowHealthBarShadow = new GUIProgressBar(new RectTransform(new Vector2(0.91f, 1.0f), healthBarContainer.RectTransform, Anchor.CenterRight),
|
||||
barSize: 1.0f, color: GUI.Style.Green, style: "GUIHealthBar")
|
||||
barSize: 1.0f, color: GUIStyle.Green, style: "GUIHealthBar")
|
||||
{
|
||||
IsHorizontal = true
|
||||
};
|
||||
healthWindowHealthBar = new GUIProgressBar(new RectTransform(new Vector2(0.91f, 1.0f), healthBarContainer.RectTransform, Anchor.CenterRight),
|
||||
barSize: 1.0f, color: GUI.Style.Green, style: "GUIHealthBar")
|
||||
barSize: 1.0f, color: GUIStyle.Green, style: "GUIHealthBar")
|
||||
{
|
||||
IsHorizontal = true
|
||||
};
|
||||
@@ -290,7 +300,7 @@ namespace Barotrauma
|
||||
|
||||
if (GameMain.Client != null)
|
||||
{
|
||||
GameMain.Client.CreateEntityEvent(Character.Controlled, new object[] { NetEntityEvent.Type.Treatment });
|
||||
GameMain.Client.CreateEntityEvent(Character.Controlled, new Character.TreatmentEventData());
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -311,7 +321,7 @@ namespace Barotrauma
|
||||
}
|
||||
);
|
||||
deadIndicator = new GUITextBlock(new RectTransform(new Vector2(0.9f, 0.1f), limbSelection.RectTransform, Anchor.Center),
|
||||
text: TextManager.Get("Deceased"), font: GUI.LargeFont, textAlignment: Alignment.Center, style: "GUIToolTip")
|
||||
text: TextManager.Get("Deceased"), font: GUIStyle.LargeFont, textAlignment: Alignment.Center, style: "GUIToolTip")
|
||||
{
|
||||
Visible = false,
|
||||
CanBeFocused = false
|
||||
@@ -328,7 +338,7 @@ namespace Barotrauma
|
||||
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);
|
||||
TextManager.Get("SuitableTreatments"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.BottomCenter);
|
||||
|
||||
treatmentLayout = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), healthWindowVerticalLayout.RectTransform), true)
|
||||
{
|
||||
@@ -366,10 +376,10 @@ namespace Barotrauma
|
||||
healthShadowSize = 1.0f;
|
||||
|
||||
healthBar = new GUIProgressBar(new RectTransform(Vector2.One, healthBarHolder.RectTransform, Anchor.BottomRight),
|
||||
barSize: 1.0f, color: GUI.Style.HealthBarColorHigh, style: "CharacterHealthBar")
|
||||
barSize: 1.0f, color: GUIStyle.HealthBarColorHigh, style: "CharacterHealthBar")
|
||||
{
|
||||
HoverCursor = CursorState.Hand,
|
||||
ToolTip = TextManager.GetWithVariable("hudbutton.healthinterface", "[key]", GameMain.Config.KeyBindText(InputType.Health)),
|
||||
ToolTip = TextManager.GetWithVariable("hudbutton.healthinterface", "[key]", GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Health)),
|
||||
Enabled = true
|
||||
};
|
||||
|
||||
@@ -390,7 +400,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (GameMain.Client != null)
|
||||
{
|
||||
GameMain.Client.CreateEntityEvent(Character.Controlled, new object[] { NetEntityEvent.Type.Status });
|
||||
GameMain.Client.CreateEntityEvent(Character.Controlled, new Character.CharacterStatusEventData());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -406,7 +416,7 @@ namespace Barotrauma
|
||||
|
||||
if (element != null)
|
||||
{
|
||||
foreach (XElement subElement in element.Elements())
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
@@ -501,7 +511,17 @@ namespace Barotrauma
|
||||
{
|
||||
if (prevOxygen > 0.0f && OxygenAmount <= 0.0f && Character.Controlled == Character)
|
||||
{
|
||||
SoundPlayer.PlaySound(Character.Info != null && Character.Info.Gender == Gender.Female ? "drownfemale" : "drownmale");
|
||||
string soundName;
|
||||
if (Character.Info != null)
|
||||
{
|
||||
soundName = Character.Info.ReplaceVars($"drown[{Character.Info.Prefab.MenuCategoryVar}]");
|
||||
}
|
||||
else
|
||||
{
|
||||
var charInfoPrefab = CharacterPrefab.HumanPrefab.CharacterInfoPrefab;
|
||||
soundName = charInfoPrefab.ReplaceVars($"drown[{charInfoPrefab.MenuCategoryVar}]", charInfoPrefab.Heads.First());
|
||||
}
|
||||
SoundPlayer.PlaySound(soundName);
|
||||
}
|
||||
|
||||
if (Character == Character.Controlled && !IsUnconscious && !Character.IsDead && OxygenAmount < LowOxygenThreshold)
|
||||
@@ -553,10 +573,10 @@ namespace Barotrauma
|
||||
inWater ? Character.Params.BleedParticleWater : Character.Params.BleedParticleAir,
|
||||
limb.WorldPosition, velocity, 0.0f, Character.AnimController.CurrentHull);
|
||||
|
||||
if (blood != null && !inWater)
|
||||
if (blood != null)
|
||||
{
|
||||
blood.Size *= bloodParticleSize;
|
||||
if (!string.IsNullOrEmpty(Character.BloodDecalName) && Rand.Range(0.0f, 1.0f) < 0.05f)
|
||||
if (!inWater && !string.IsNullOrEmpty(Character.BloodDecalName) && Rand.Range(0.0f, 1.0f) < 0.05f)
|
||||
{
|
||||
blood.OnCollision += (Vector2 pos, Hull hull) =>
|
||||
{
|
||||
@@ -715,11 +735,11 @@ namespace Barotrauma
|
||||
if (!(afflictionIcon.UserData is Affliction affliction)) { continue; }
|
||||
if (affliction.AppliedAsFailedTreatmentTime > Timing.TotalTime - 1.0 && afflictionIcon.FlashTimer <= 0.0f)
|
||||
{
|
||||
afflictionIcon.Flash(GUI.Style.Red);
|
||||
afflictionIcon.Flash(GUIStyle.Red);
|
||||
}
|
||||
else if (affliction.AppliedAsSuccessfulTreatmentTime > Timing.TotalTime - 1.0 && afflictionIcon.FlashTimer <= 0.0f)
|
||||
{
|
||||
afflictionIcon.Flash(GUI.Style.Green);
|
||||
afflictionIcon.Flash(GUIStyle.Green);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -754,7 +774,7 @@ namespace Barotrauma
|
||||
|
||||
var labelContainer = afflictionTooltip.Content.GetChildByUserData("label");
|
||||
|
||||
labelContainer.RectTransform.Resize(new Point(labelContainer.Rect.Width, (int)(GUI.LargeFont.Size * 1.5f)));
|
||||
labelContainer.RectTransform.Resize(new Point(labelContainer.Rect.Width, (int)(GUIStyle.LargeFont.Size * 1.5f)));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -799,7 +819,7 @@ namespace Barotrauma
|
||||
{
|
||||
var treatmentButton = component.GetChild<GUIButton>();
|
||||
if (!(treatmentButton?.UserData is ItemPrefab itemPrefab)) { continue; }
|
||||
var matchingItem = Character.Controlled.Inventory.FindItem(it => it.prefab == itemPrefab, recursive: true);
|
||||
var matchingItem = Character.Controlled.Inventory.FindItem(it => it.Prefab == itemPrefab, recursive: true);
|
||||
treatmentButton.Enabled = matchingItem != null;
|
||||
if (treatmentButton.Enabled && treatmentButton.State == GUIComponent.ComponentState.Hover)
|
||||
{
|
||||
@@ -809,16 +829,18 @@ namespace Barotrauma
|
||||
if (Character.Controlled.Inventory.visualSlots != null && index > -1 && index < Character.Controlled.Inventory.visualSlots.Length &&
|
||||
Character.Controlled.Inventory.visualSlots[index].HighlightTimer <= 0.0f)
|
||||
{
|
||||
Character.Controlled.Inventory.visualSlots[index].ShowBorderHighlight(GUI.Style.Green, 0.5f, 0.5f);
|
||||
Character.Controlled.Inventory.visualSlots[index].ShowBorderHighlight(GUIStyle.Green, 0.5f, 0.5f);
|
||||
}
|
||||
}
|
||||
if (matchingItem != null && !string.IsNullOrEmpty(treatmentButton.ToolTip)) { continue; }
|
||||
treatmentButton.ToolTip = $"‖color:255,255,255,255‖{itemPrefab.Name}‖color:end‖" + '\n' + itemPrefab.Description;
|
||||
if (matchingItem != null && !treatmentButton.ToolTip.IsNullOrEmpty()) { continue; }
|
||||
treatmentButton.ToolTip = RichString.Rich($"‖color:255,255,255,255‖{itemPrefab.Name}‖color:end‖" + '\n' + itemPrefab.Description);
|
||||
if (treatmentButton.Enabled)
|
||||
{
|
||||
treatmentButton.ToolTip =
|
||||
$"‖color:gui.green‖[{TextManager.Get(PlayerInput.MouseButtonsSwapped() ? "input.rightmouse" : "input.leftmouse")}] {TextManager.Get("quickuseaction.usetreatment")}‖color:end‖" + '\n'
|
||||
+ treatmentButton.RawToolTip;
|
||||
RichString.Rich(
|
||||
$"‖color:gui.green‖[{TextManager.Get(PlayerInput.MouseButtonsSwapped() ? "input.rightmouse" : "input.leftmouse")}] "
|
||||
+ $"{TextManager.Get("quickuseaction.usetreatment")}‖color:end‖" + '\n'
|
||||
+ treatmentButton.ToolTip.NestedStr);
|
||||
}
|
||||
foreach (GUIComponent child in treatmentButton.Children)
|
||||
{
|
||||
@@ -834,7 +856,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
healthBar.Color = healthWindowHealthBar.Color = ToolBox.GradientLerp(DisplayedVitality / MaxVitality, GUI.Style.HealthBarColorLow, GUI.Style.HealthBarColorMedium, GUI.Style.HealthBarColorHigh);
|
||||
healthBar.Color = healthWindowHealthBar.Color = ToolBox.GradientLerp(DisplayedVitality / MaxVitality, GUIStyle.HealthBarColorLow, GUIStyle.HealthBarColorMedium, GUIStyle.HealthBarColorHigh);
|
||||
healthBar.HoverColor = healthWindowHealthBar.HoverColor = healthBar.Color * 2.0f;
|
||||
healthBar.BarSize = healthWindowHealthBar.BarSize =
|
||||
(DisplayedVitality > 0.0f) ?
|
||||
@@ -1007,14 +1029,14 @@ namespace Barotrauma
|
||||
DrawStatusHUD(spriteBatch);
|
||||
}
|
||||
|
||||
private (Affliction affliction, string text)? highlightedAfflictionIcon;
|
||||
private (Affliction Affliction, LocalizedString NameToolTip)? highlightedAfflictionIcon = null;
|
||||
public void DrawStatusHUD(SpriteBatch spriteBatch)
|
||||
{
|
||||
highlightedAfflictionIcon = null;
|
||||
//Rectangle interactArea = healthBar.Rect;
|
||||
if (Character.Controlled?.SelectedCharacter == null && openHealthWindow == null)
|
||||
{
|
||||
List<(Affliction affliction, string text)> statusIcons = new List<(Affliction affliction, string text)>();
|
||||
var statusIcons = new List<(Affliction Affliction, LocalizedString Warning)>();
|
||||
if (Character.InPressure)
|
||||
{
|
||||
statusIcons.Add((pressureAffliction, TextManager.Get("PressureHUDWarning")));
|
||||
@@ -1045,7 +1067,7 @@ namespace Barotrauma
|
||||
|
||||
foreach (var statusIcon in statusIcons)
|
||||
{
|
||||
Affliction affliction = statusIcon.affliction;
|
||||
Affliction affliction = statusIcon.Affliction;
|
||||
AfflictionPrefab afflictionPrefab = affliction.Prefab;
|
||||
|
||||
Rectangle afflictionIconRect = new Rectangle(pos, new Point(iconSize));
|
||||
@@ -1059,10 +1081,10 @@ namespace Barotrauma
|
||||
{
|
||||
Rectangle glowRect = afflictionIconRect;
|
||||
glowRect.Inflate((int)(20 * GUI.Scale), (int)(20 * GUI.Scale));
|
||||
var glow = GUI.Style.GetComponentStyle("OuterGlowCircular");
|
||||
var glow = GUIStyle.GetComponentStyle("OuterGlowCircular");
|
||||
glow.Sprites[GUIComponent.ComponentState.None][0].Draw(
|
||||
spriteBatch, glowRect,
|
||||
GUI.Style.Red * (float)((Math.Sin(affliction.DamagePerSecondTimer * MathHelper.TwoPi - MathHelper.PiOver2) + 1.0f) * 0.5f));
|
||||
GUIStyle.Red * (float)((Math.Sin(affliction.DamagePerSecondTimer * MathHelper.TwoPi - MathHelper.PiOver2) + 1.0f) * 0.5f));
|
||||
}
|
||||
|
||||
float alphaMultiplier = highlightedAfflictionIcon == statusIcon ? 1f : 0.8f;
|
||||
@@ -1082,8 +1104,8 @@ namespace Barotrauma
|
||||
|
||||
if (highlightedAfflictionIcon != null)
|
||||
{
|
||||
string nameTooltip = highlightedAfflictionIcon.Value.text;
|
||||
Vector2 offset = GUI.Font.MeasureString(nameTooltip);
|
||||
LocalizedString nameTooltip = highlightedAfflictionIcon.Value.NameToolTip;
|
||||
Vector2 offset = GUIStyle.Font.MeasureString(nameTooltip);
|
||||
|
||||
GUI.DrawString(spriteBatch,
|
||||
alignment == Alignment.Left ? highlightedIconPos + offset : highlightedIconPos - offset,
|
||||
@@ -1096,7 +1118,7 @@ namespace Barotrauma
|
||||
float currHealth = healthBar.BarSize;
|
||||
Color prevColor = healthBar.Color;
|
||||
healthBarShadow.BarSize = healthShadowSize;
|
||||
healthBarShadow.Color = Color.Lerp(GUI.Style.Red, Color.Black, 0.5f);
|
||||
healthBarShadow.Color = Color.Lerp(GUIStyle.Red, Color.Black, 0.5f);
|
||||
healthBarShadow.Visible = true;
|
||||
healthBar.BarSize = currHealth;
|
||||
healthBar.Color = prevColor;
|
||||
@@ -1113,7 +1135,7 @@ namespace Barotrauma
|
||||
float currHealth = healthWindowHealthBar.BarSize;
|
||||
Color prevColor = healthWindowHealthBar.Color;
|
||||
healthWindowHealthBarShadow.BarSize = healthShadowSize;
|
||||
healthWindowHealthBarShadow.Color = GUI.Style.Red;
|
||||
healthWindowHealthBarShadow.Color = GUIStyle.Red;
|
||||
healthWindowHealthBarShadow.Visible = true;
|
||||
healthWindowHealthBar.BarSize = currHealth;
|
||||
healthWindowHealthBar.Color = prevColor;
|
||||
@@ -1137,10 +1159,10 @@ namespace Barotrauma
|
||||
{
|
||||
if (prefab.IsBuff)
|
||||
{
|
||||
return ToolBox.GradientLerp(afflictionStrength / prefab.MaxStrength, GUI.Style.BuffColorLow, GUI.Style.BuffColorMedium, GUI.Style.BuffColorHigh);
|
||||
return ToolBox.GradientLerp(afflictionStrength / prefab.MaxStrength, GUIStyle.BuffColorLow, GUIStyle.BuffColorMedium, GUIStyle.BuffColorHigh);
|
||||
}
|
||||
|
||||
return ToolBox.GradientLerp(afflictionStrength / prefab.MaxStrength, GUI.Style.DebuffColorLow, GUI.Style.DebuffColorMedium, GUI.Style.DebuffColorHigh);
|
||||
return ToolBox.GradientLerp(afflictionStrength / prefab.MaxStrength, GUIStyle.DebuffColorLow, GUIStyle.DebuffColorMedium, GUIStyle.DebuffColorHigh);
|
||||
}
|
||||
|
||||
return ToolBox.GradientLerp(afflictionStrength / prefab.MaxStrength, prefab.IconColors);
|
||||
@@ -1213,7 +1235,7 @@ namespace Barotrauma
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
var progressbarBg = new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.18f), content.RectTransform), 0.0f, GUI.Style.Green, style: "GUIAfflictionBar")
|
||||
var progressbarBg = new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.18f), content.RectTransform), 0.0f, GUIStyle.Green, style: "GUIAfflictionBar")
|
||||
{
|
||||
UserData = "afflictionstrengthprediction",
|
||||
CanBeFocused = false
|
||||
@@ -1240,9 +1262,9 @@ namespace Barotrauma
|
||||
afflictionIcon.PressedColor = afflictionIcon.Color;
|
||||
afflictionIcon.HoverColor = Color.Lerp(afflictionIcon.Color, Color.White, 0.6f);
|
||||
afflictionIcon.SelectedColor = Color.Lerp(afflictionIcon.Color, Color.White, 0.5f);
|
||||
|
||||
|
||||
var nameText = new GUITextBlock(new RectTransform(new Vector2(1.1f, 0.0f), content.RectTransform),
|
||||
affliction.Prefab.Name, font: GUI.SmallFont, textAlignment: Alignment.BottomCenter)
|
||||
affliction.Prefab.Name, font: GUIStyle.SmallFont, textAlignment: Alignment.BottomCenter)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
@@ -1274,13 +1296,13 @@ namespace Barotrauma
|
||||
|
||||
//key = item identifier
|
||||
//float = suitability
|
||||
Dictionary<string, float> treatmentSuitability = new Dictionary<string, float>();
|
||||
Dictionary<Identifier, float> treatmentSuitability = new Dictionary<Identifier, 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())
|
||||
foreach (Identifier treatment in treatmentSuitability.Keys.ToList())
|
||||
{
|
||||
//prefer suggestions for items the player has
|
||||
if (Character.Controlled.Inventory.FindItemByIdentifier(treatment, recursive: true) != null)
|
||||
@@ -1304,10 +1326,10 @@ namespace Barotrauma
|
||||
recommendedTreatmentContainer.AutoHideScrollBar = true;
|
||||
}
|
||||
|
||||
List<KeyValuePair<string, float>> treatmentSuitabilities = treatmentSuitability.OrderByDescending(t => t.Value).ToList();
|
||||
List<KeyValuePair<Identifier, float>> treatmentSuitabilities = treatmentSuitability.OrderByDescending(t => t.Value).ToList();
|
||||
|
||||
int count = 0;
|
||||
foreach (KeyValuePair<string, float> treatment in treatmentSuitabilities)
|
||||
foreach (KeyValuePair<Identifier, float> treatment in treatmentSuitabilities)
|
||||
{
|
||||
count++;
|
||||
if (count > 5) { break; }
|
||||
@@ -1326,7 +1348,7 @@ namespace Barotrauma
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
if (!(userdata is ItemPrefab itemPrefab)) { return false; }
|
||||
var item = Character.Controlled.Inventory.FindItem(it => it.prefab == itemPrefab, recursive: true);
|
||||
var item = Character.Controlled.Inventory.FindItem(it => it.Prefab == itemPrefab, recursive: true);
|
||||
if (item == null) { return false; }
|
||||
Limb targetLimb = Character.AnimController.Limbs.FirstOrDefault(l => l.HealthIndex == selectedLimbIndex);
|
||||
item.ApplyTreatment(Character.Controlled, Character, targetLimb);
|
||||
@@ -1337,15 +1359,15 @@ namespace Barotrauma
|
||||
new GUIImage(new RectTransform(Vector2.One, innerFrame.RectTransform, Anchor.Center), style: "TalentBackgroundGlow")
|
||||
{
|
||||
CanBeFocused = false,
|
||||
Color = GUI.Style.Green,
|
||||
Color = GUIStyle.Green,
|
||||
HoverColor = Color.White,
|
||||
PressedColor = Color.DarkGray,
|
||||
SelectedColor = Color.Transparent,
|
||||
DisabledColor = Color.Transparent
|
||||
};
|
||||
|
||||
Sprite itemSprite = item.InventoryIcon ?? item.sprite;
|
||||
Color itemColor = itemSprite == item.sprite ? item.SpriteColor : item.InventoryIconColor;
|
||||
Sprite itemSprite = item.InventoryIcon ?? item.Sprite;
|
||||
Color itemColor = itemSprite == item.Sprite ? item.SpriteColor : item.InventoryIconColor;
|
||||
var itemIcon = new GUIImage(new RectTransform(new Vector2(0.8f, 0.8f), innerFrame.RectTransform, Anchor.Center),
|
||||
itemSprite, scaleToFit: true)
|
||||
{
|
||||
@@ -1397,12 +1419,12 @@ namespace Barotrauma
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
var afflictionName = new GUITextBlock(new RectTransform(new Vector2(0.65f, 1.0f), labelContainer.RectTransform), affliction.Prefab.Name, textAlignment: Alignment.CenterLeft, font: GUI.LargeFont)
|
||||
var afflictionName = new GUITextBlock(new RectTransform(new Vector2(0.65f, 1.0f), labelContainer.RectTransform), affliction.Prefab.Name, textAlignment: Alignment.CenterLeft, font: GUIStyle.LargeFont)
|
||||
{
|
||||
CanBeFocused = false,
|
||||
AutoScaleHorizontal = true
|
||||
};
|
||||
var afflictionStrength = new GUITextBlock(new RectTransform(new Vector2(0.35f, 0.6f), labelContainer.RectTransform), "", textAlignment: Alignment.TopRight, font: GUI.SubHeadingFont)
|
||||
var afflictionStrength = new GUITextBlock(new RectTransform(new Vector2(0.35f, 0.6f), labelContainer.RectTransform), "", textAlignment: Alignment.TopRight, font: GUIStyle.SubHeadingFont)
|
||||
{
|
||||
UserData = "strength",
|
||||
CanBeFocused = false
|
||||
@@ -1423,21 +1445,21 @@ namespace Barotrauma
|
||||
|
||||
if (description.Font.MeasureString(description.WrappedText).Y > description.Rect.Height)
|
||||
{
|
||||
description.Font = GUI.SmallFont;
|
||||
description.Font = GUIStyle.SmallFont;
|
||||
}
|
||||
|
||||
Point nameDims = new Point(afflictionName.Rect.Width, (int)(GUI.LargeFont.Size * 1.5f));
|
||||
Point nameDims = new Point(afflictionName.Rect.Width, (int)(GUIStyle.LargeFont.Size * 1.5f));
|
||||
|
||||
afflictionStrength.Text = strengthTexts[
|
||||
MathHelper.Clamp((int)Math.Floor((affliction.Strength / affliction.Prefab.MaxStrength) * strengthTexts.Length), 0, strengthTexts.Length - 1)];
|
||||
|
||||
Vector2 strengthDims = GUI.SubHeadingFont.MeasureString(afflictionStrength.Text);
|
||||
Vector2 strengthDims = GUIStyle.SubHeadingFont.MeasureString(afflictionStrength.Text);
|
||||
|
||||
labelContainer.RectTransform.Resize(new Point(labelContainer.Rect.Width, nameDims.Y));
|
||||
afflictionName.RectTransform.Resize(new Point((int)(labelContainer.Rect.Width - strengthDims.X * 0.99f), nameDims.Y));
|
||||
afflictionStrength.RectTransform.Resize(new Point(labelContainer.Rect.Width - afflictionName.Rect.Width, nameDims.Y));
|
||||
|
||||
afflictionStrength.TextColor = Color.Lerp(GUI.Style.Orange, GUI.Style.Red,
|
||||
afflictionStrength.TextColor = Color.Lerp(GUIStyle.Orange, GUIStyle.Red,
|
||||
affliction.Strength / affliction.Prefab.MaxStrength);
|
||||
|
||||
description.RectTransform.Resize(new Point(description.Rect.Width, (int)(description.TextSize.Y + 10)));
|
||||
@@ -1451,8 +1473,8 @@ namespace Barotrauma
|
||||
{
|
||||
vitality.Visible = true;
|
||||
vitality.Text = TextManager.Get("Vitality") + " -" + vitalityDecrease;
|
||||
vitality.TextColor = vitalityDecrease <= 0 ? GUI.Style.Green :
|
||||
Color.Lerp(GUI.Style.Orange, GUI.Style.Red, affliction.Strength / affliction.Prefab.MaxStrength);
|
||||
vitality.TextColor = vitalityDecrease <= 0 ? GUIStyle.Green :
|
||||
Color.Lerp(GUIStyle.Orange, GUIStyle.Red, affliction.Strength / affliction.Prefab.MaxStrength);
|
||||
}
|
||||
|
||||
vitality.AutoDraw = true;
|
||||
@@ -1478,7 +1500,7 @@ namespace Barotrauma
|
||||
var potentialTreatment = Inventory.DraggingItems.FirstOrDefault();
|
||||
if (potentialTreatment == null && GUI.MouseOn?.UserData is ItemPrefab itemPrefab)
|
||||
{
|
||||
potentialTreatment = Character.Controlled.Inventory.FindItem(it => it.prefab == itemPrefab, recursive: true);
|
||||
potentialTreatment = Character.Controlled.Inventory.FindItem(it => it.Prefab == itemPrefab, recursive: true);
|
||||
}
|
||||
potentialTreatment ??= Inventory.SelectedSlot?.Item;
|
||||
|
||||
@@ -1488,11 +1510,11 @@ namespace Barotrauma
|
||||
Color afflictionEffectColor = Color.White;
|
||||
if (afflictionVitalityDecrease > 0.0f)
|
||||
{
|
||||
afflictionEffectColor = GUI.Style.Red;
|
||||
afflictionEffectColor = GUIStyle.Red;
|
||||
}
|
||||
else if (afflictionVitalityDecrease < 0.0f)
|
||||
{
|
||||
afflictionEffectColor = GUI.Style.Green;
|
||||
afflictionEffectColor = GUIStyle.Green;
|
||||
}
|
||||
|
||||
var child = afflictionIconContainer.Content.FindChild(affliction);
|
||||
@@ -1510,7 +1532,7 @@ namespace Barotrauma
|
||||
if (afflictionStrengthPrediction < affliction.Strength)
|
||||
{
|
||||
afflictionStrengthBar.Color = afflictionEffectColor;
|
||||
afflictionStrengthPredictionBar.Color = GUI.Style.Blue * t;
|
||||
afflictionStrengthPredictionBar.Color = GUIStyle.Blue * t;
|
||||
afflictionStrengthPredictionBar.BarSize = afflictionStrengthBar.BarSize;
|
||||
afflictionStrengthBar.BarSize = afflictionStrengthPrediction / affliction.Prefab.MaxStrength;
|
||||
}
|
||||
@@ -1541,8 +1563,8 @@ namespace Barotrauma
|
||||
{
|
||||
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);
|
||||
if (reduceAffliction.AfflictionIdentifier != affliction.Identifier && reduceAffliction.AfflictionIdentifier != affliction.Prefab.AfflictionType) { continue; }
|
||||
strength -= reduceAffliction.ReduceAmount * (effect.Duration > 0 ? effect.Duration : 1.0f);
|
||||
}
|
||||
foreach (var addAffliction in effect.Afflictions)
|
||||
{
|
||||
@@ -1563,7 +1585,7 @@ namespace Barotrauma
|
||||
strengthText.Text = strengthTexts[
|
||||
MathHelper.Clamp((int)Math.Floor((affliction.Strength / affliction.Prefab.MaxStrength) * strengthTexts.Length), 0, strengthTexts.Length - 1)];
|
||||
|
||||
strengthText.TextColor = Color.Lerp(GUI.Style.Orange, GUI.Style.Red,
|
||||
strengthText.TextColor = Color.Lerp(GUIStyle.Orange, GUIStyle.Red,
|
||||
affliction.Strength / affliction.Prefab.MaxStrength);
|
||||
|
||||
var vitalityText = labelContainer.GetChildByUserData("vitality") as GUITextBlock;
|
||||
@@ -1576,8 +1598,8 @@ namespace Barotrauma
|
||||
{
|
||||
vitalityText.Visible = true;
|
||||
vitalityText.Text = TextManager.Get("Vitality") + " -" + vitalityDecrease;
|
||||
vitalityText.TextColor = vitalityDecrease <= 0 ? GUI.Style.Green :
|
||||
Color.Lerp(GUI.Style.Orange, GUI.Style.Red, affliction.Strength / affliction.Prefab.MaxStrength);
|
||||
vitalityText.TextColor = vitalityDecrease <= 0 ? GUIStyle.Green :
|
||||
Color.Lerp(GUIStyle.Orange, GUIStyle.Red, affliction.Strength / affliction.Prefab.MaxStrength);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1807,9 +1829,9 @@ namespace Barotrauma
|
||||
if (afflictionsDisplayedOnLimb.Count() > 1)
|
||||
{
|
||||
string additionalAfflictionCount = $"+{afflictionsDisplayedOnLimb.Count() - 1}";
|
||||
Vector2 displace = GUI.SubHeadingFont.MeasureString(additionalAfflictionCount);
|
||||
GUI.SubHeadingFont.DrawString(spriteBatch, additionalAfflictionCount, iconPos + new Vector2(displace.X * 1.1f, -displace.Y * 0.45f), Color.Black * 0.75f);
|
||||
GUI.SubHeadingFont.DrawString(spriteBatch, additionalAfflictionCount, iconPos + new Vector2(displace.X, -displace.Y * 0.5f), Color.White);
|
||||
Vector2 displace = GUIStyle.SubHeadingFont.MeasureString(additionalAfflictionCount);
|
||||
GUIStyle.SubHeadingFont.DrawString(spriteBatch, additionalAfflictionCount, iconPos + new Vector2(displace.X * 1.1f, -displace.Y * 0.45f), Color.Black * 0.75f);
|
||||
GUIStyle.SubHeadingFont.DrawString(spriteBatch, additionalAfflictionCount, iconPos + new Vector2(displace.X, -displace.Y * 0.5f), Color.White);
|
||||
}
|
||||
|
||||
i++;
|
||||
@@ -1885,7 +1907,7 @@ namespace Barotrauma
|
||||
for (int i = 0; i < afflictionCount; i++)
|
||||
{
|
||||
uint afflictionID = inc.ReadUInt32();
|
||||
AfflictionPrefab afflictionPrefab = AfflictionPrefab.Prefabs.Find(p => p.UIntIdentifier == afflictionID);
|
||||
AfflictionPrefab afflictionPrefab = AfflictionPrefab.Prefabs.Find(p => p.UintIdentifier == afflictionID);
|
||||
if (afflictionPrefab == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Error while reading character health data: affliction with the uint ID " + afflictionID + " not found.");
|
||||
@@ -1913,7 +1935,7 @@ namespace Barotrauma
|
||||
{
|
||||
int limbIndex = inc.ReadRangedInteger(0, limbHealths.Count - 1);
|
||||
uint afflictionID = inc.ReadUInt32();
|
||||
AfflictionPrefab afflictionPrefab = AfflictionPrefab.Prefabs.Find(p => p.UIntIdentifier == afflictionID);
|
||||
AfflictionPrefab afflictionPrefab = AfflictionPrefab.Prefabs.Find(p => p.UintIdentifier == afflictionID);
|
||||
if (afflictionPrefab == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Error while reading character health data: affliction with the uint ID " + afflictionID + " not found.");
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
{
|
||||
partial class DamageModifier
|
||||
{
|
||||
[Serialize("", false), Editable]
|
||||
[Serialize("", IsPropertySaveable.No), Editable]
|
||||
public string DamageSound
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
[Serialize("", false), Editable]
|
||||
[Serialize("", IsPropertySaveable.No), Editable]
|
||||
public string DamageParticle
|
||||
{
|
||||
get;
|
||||
|
||||
@@ -6,7 +6,7 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class JobPrefab : IPrefab, IDisposable
|
||||
partial class JobPrefab : PrefabWithUintIdentifier
|
||||
{
|
||||
public GUIButton CreateInfoFrame(out GUIComponent buttonContainer)
|
||||
{
|
||||
@@ -18,20 +18,20 @@ namespace Barotrauma
|
||||
GUIFrame frame = new GUIFrame(new RectTransform(new Point(width, height), frameHolder.RectTransform, Anchor.Center));
|
||||
GUIFrame paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.9f), frame.RectTransform, Anchor.Center), style: null);
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), paddedFrame.RectTransform), Name, font: GUI.LargeFont);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), paddedFrame.RectTransform), Name, font: GUIStyle.LargeFont);
|
||||
|
||||
var descriptionBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.15f) },
|
||||
Description, font: GUI.SmallFont, wrap: true);
|
||||
Description, font: GUIStyle.SmallFont, wrap: true);
|
||||
|
||||
var skillContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.45f, 0.5f), paddedFrame.RectTransform)
|
||||
{ RelativeOffset = new Vector2(0.0f, 0.2f + descriptionBlock.RectTransform.RelativeSize.Y) });
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), skillContainer.RectTransform),
|
||||
TextManager.Get("Skills"), font: GUI.LargeFont);
|
||||
TextManager.Get("Skills"), font: GUIStyle.LargeFont);
|
||||
foreach (SkillPrefab skill in Skills)
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), skillContainer.RectTransform),
|
||||
" - " + TextManager.AddPunctuation(':', TextManager.Get("SkillName." + skill.Identifier), (int)skill.LevelRange.Start + " - " + (int)skill.LevelRange.End),
|
||||
font: GUI.SmallFont);
|
||||
font: GUIStyle.SmallFont);
|
||||
}
|
||||
|
||||
buttonContainer = paddedFrame;
|
||||
@@ -43,14 +43,14 @@ namespace Barotrauma
|
||||
Stretch = true
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), itemContainer.RectTransform),
|
||||
TextManager.Get("Items", fallBackTag: "mapentitycategory.equipment"), font: GUI.LargeFont);
|
||||
TextManager.Get("Items", "mapentitycategory.equipment"), font: GUIStyle.LargeFont);
|
||||
foreach (string identifier in itemIdentifiers.Distinct())
|
||||
{
|
||||
if (!(MapEntityPrefab.Find(name: null, identifier: identifier) is ItemPrefab itemPrefab)) { continue; }
|
||||
int count = itemIdentifiers.Count(i => i == identifier);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), itemContainer.RectTransform),
|
||||
" - " + (count == 1 ? itemPrefab.Name : itemPrefab.Name + " x" + count),
|
||||
font: GUI.SmallFont);
|
||||
font: GUIStyle.SmallFont);
|
||||
}*/
|
||||
|
||||
return frameHolder;
|
||||
@@ -76,12 +76,12 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public List<OutfitPreview> GetJobOutfitSprites(Gender gender, bool useInventoryIcon, out Vector2 maxDimensions)
|
||||
public List<OutfitPreview> GetJobOutfitSprites(CharacterInfoPrefab charInfoPrefab, bool useInventoryIcon, out Vector2 maxDimensions)
|
||||
{
|
||||
List<OutfitPreview> outfitPreviews = new List<OutfitPreview>();
|
||||
maxDimensions = Vector2.One;
|
||||
|
||||
var equipIdentifiers = Element.GetChildElements("ItemSet").Elements().Where(e => e.GetAttributeBool("outfit", false)).Select(e => e.GetAttributeString("identifier", ""));
|
||||
var equipIdentifiers = Element.GetChildElements("ItemSet").Elements().Where(e => e.GetAttributeBool("outfit", false)).Select(e => e.GetAttributeIdentifier("identifier", ""));
|
||||
|
||||
List<ItemPrefab> outfitPrefabs = new List<ItemPrefab>();
|
||||
foreach (var equipIdentifier in equipIdentifiers)
|
||||
@@ -114,8 +114,8 @@ namespace Barotrauma
|
||||
var children = previewElement.Elements().ToList();
|
||||
for (int n = 0; n < children.Count; n++)
|
||||
{
|
||||
XElement spriteElement = children[n];
|
||||
string spriteTexture = spriteElement.GetAttributeString("texture", "").Replace("[GENDER]", (gender == Gender.Female) ? "female" : "male");
|
||||
var spriteElement = children[n];
|
||||
string spriteTexture = charInfoPrefab.ReplaceVars(spriteElement.GetAttributeString("texture", ""), charInfoPrefab.Heads.First());
|
||||
var sprite = new Sprite(spriteElement, file: spriteTexture);
|
||||
sprite.size = new Vector2(sprite.SourceRect.Width, sprite.SourceRect.Height);
|
||||
outfitPreview.AddSprite(sprite, children[n].GetAttributeVector2("offset", Vector2.Zero));
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace Barotrauma
|
||||
//{
|
||||
// var pos = ConvertUnits.ToDisplayUnits(mouthPos.Value);
|
||||
// pos.Y = -pos.Y;
|
||||
// ShapeExtensions.DrawPoint(spriteBatch, pos, GUI.Style.Red, size: 5);
|
||||
// ShapeExtensions.DrawPoint(spriteBatch, pos, GUIStyle.Red, size: 5);
|
||||
//}
|
||||
|
||||
// A debug visualisation on the bezier curve between limbs.
|
||||
@@ -95,7 +95,7 @@ namespace Barotrauma
|
||||
GUI.DrawLine(spriteBatch, start, end, Color.White);
|
||||
GUI.DrawLine(spriteBatch, start, control, Color.Black);
|
||||
GUI.DrawLine(spriteBatch, control, end, Color.Black);
|
||||
GUI.DrawBezierWithDots(spriteBatch, start, end, control, 1000, GUI.Style.Red);*/
|
||||
GUI.DrawBezierWithDots(spriteBatch, start, end, control, 1000, GUIStyle.Red);*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,7 +274,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
partial void InitProjSpecific(XElement element)
|
||||
partial void InitProjSpecific(ContentXElement element)
|
||||
{
|
||||
for (int i = 0; i < Params.decorativeSpriteParams.Count; i++)
|
||||
{
|
||||
@@ -290,7 +290,7 @@ namespace Barotrauma
|
||||
spriteAnimState.Add(decorativeSprite, new SpriteState());
|
||||
}
|
||||
TintMask = null;
|
||||
foreach (XElement subElement in element.Elements())
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
@@ -317,7 +317,7 @@ namespace Barotrauma
|
||||
NonConditionalDeformations.AddRange(deformations);
|
||||
break;
|
||||
case "randomcolor":
|
||||
randomColor = subElement.GetAttributeColorArray("colors", null)?.GetRandom();
|
||||
randomColor = subElement.GetAttributeColorArray("colors", null)?.GetRandomUnsynced();
|
||||
if (randomColor.HasValue)
|
||||
{
|
||||
Params.GetSprite().Color = randomColor.Value;
|
||||
@@ -337,8 +337,8 @@ namespace Barotrauma
|
||||
InitialLightSpriteAlpha = LightSource.OverrideLightSpriteAlpha;
|
||||
break;
|
||||
case "tintmask":
|
||||
string tintMaskPath = subElement.GetAttributeString("texture", "");
|
||||
if (!string.IsNullOrWhiteSpace(tintMaskPath))
|
||||
ContentPath tintMaskPath = subElement.GetAttributeContentPath("texture");
|
||||
if (!tintMaskPath.IsNullOrWhiteSpace())
|
||||
{
|
||||
TintMask = new Sprite(subElement, file: GetSpritePath(tintMaskPath));
|
||||
TintHighlightThreshold = subElement.GetAttributeFloat("highlightthreshold", 0.6f);
|
||||
@@ -346,8 +346,8 @@ namespace Barotrauma
|
||||
}
|
||||
break;
|
||||
case "huskmask":
|
||||
string huskMaskPath = subElement.GetAttributeString("texture", "");
|
||||
if (!string.IsNullOrWhiteSpace(huskMaskPath))
|
||||
ContentPath huskMaskPath = subElement.GetAttributeContentPath("texture");
|
||||
if (!huskMaskPath.IsNullOrWhiteSpace())
|
||||
{
|
||||
HuskMask = new Sprite(subElement, file: GetSpritePath(huskMaskPath));
|
||||
}
|
||||
@@ -387,7 +387,7 @@ namespace Barotrauma
|
||||
}
|
||||
if (deformation == null)
|
||||
{
|
||||
deformation = SpriteDeformation.Load(animationElement, character.SpeciesName);
|
||||
deformation = SpriteDeformation.Load(animationElement, character.SpeciesName.Value);
|
||||
if (deformation != null)
|
||||
{
|
||||
ragdoll.SpriteDeformations.Add(deformation);
|
||||
@@ -472,19 +472,23 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
private string _texturePath;
|
||||
private string GetSpritePath(XElement element, SpriteParams spriteParams)
|
||||
private string GetSpritePath(ContentXElement element, SpriteParams spriteParams)
|
||||
{
|
||||
if (_texturePath == null)
|
||||
{
|
||||
if (spriteParams != null)
|
||||
{
|
||||
string texturePath = character.Params.VariantFile?.Root?.GetAttributeString("texture", null) ?? spriteParams.GetTexturePath();
|
||||
ContentPath texturePath =
|
||||
character.Params.VariantFile?.Root?.GetAttributeContentPath("texture", character.Prefab.ContentPackage)
|
||||
?? ContentPath.FromRaw(character.Prefab.ContentPackage, spriteParams.GetTexturePath());
|
||||
_texturePath = GetSpritePath(texturePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
string texturePath = element.GetAttributeString("texture", null);
|
||||
texturePath = string.IsNullOrWhiteSpace(texturePath) ? ragdoll.RagdollParams.Texture : texturePath;
|
||||
ContentPath texturePath = element.GetAttributeContentPath("texture");
|
||||
texturePath = texturePath.IsNullOrWhiteSpace()
|
||||
? ContentPath.FromRaw(character.Prefab.ContentPackage, ragdoll.RagdollParams.Texture)
|
||||
: texturePath;
|
||||
_texturePath = GetSpritePath(texturePath);
|
||||
}
|
||||
}
|
||||
@@ -494,20 +498,18 @@ namespace Barotrauma
|
||||
/// <summary>
|
||||
/// Get the full path of a limb sprite, taking into account tags, gender and head id
|
||||
/// </summary>
|
||||
public static string GetSpritePath(string texturePath, CharacterInfo characterInfo)
|
||||
public static string GetSpritePath(ContentPath texturePath, CharacterInfo characterInfo)
|
||||
{
|
||||
string spritePath = texturePath;
|
||||
string spritePath = texturePath.Value;
|
||||
string spritePathWithTags = spritePath;
|
||||
if (characterInfo != null)
|
||||
{
|
||||
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());
|
||||
spritePath = characterInfo.ReplaceVars(spritePath);
|
||||
|
||||
if (characterInfo.HeadSprite != null && characterInfo.SpriteTags.Any())
|
||||
{
|
||||
string tags = "";
|
||||
characterInfo.SpriteTags.ForEach(tag => tags += "[" + tag + "]");
|
||||
characterInfo.SpriteTags.ForEach(tag => tags += $"[{tag}]");
|
||||
|
||||
spritePathWithTags = Path.Combine(
|
||||
Path.GetDirectoryName(spritePath),
|
||||
@@ -518,10 +520,10 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
|
||||
private string GetSpritePath(string texturePath)
|
||||
private string GetSpritePath(ContentPath texturePath)
|
||||
{
|
||||
if (!character.IsHumanoid) { return texturePath; }
|
||||
return GetSpritePath(texturePath, character?.Info);
|
||||
if (!character.IsHumanoid) { return texturePath.Value; }
|
||||
return GetSpritePath(texturePath, character.Info);
|
||||
}
|
||||
|
||||
partial void LoadParamsProjSpecific()
|
||||
@@ -696,7 +698,7 @@ namespace Barotrauma
|
||||
clr = clr.Multiply(ragdoll.RagdollParams.Color);
|
||||
if (character.Info != null)
|
||||
{
|
||||
clr = clr.Multiply(character.Info.SkinColor);
|
||||
clr = clr.Multiply(character.Info.Head.SkinColor);
|
||||
}
|
||||
if (character.CharacterHealth.FaceTint.A > 0 && type == LimbType.Head)
|
||||
{
|
||||
@@ -929,7 +931,7 @@ namespace Barotrauma
|
||||
if (pullJoint != null)
|
||||
{
|
||||
Vector2 pos = ConvertUnits.ToDisplayUnits(pullJoint.WorldAnchorB);
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 5, 5), GUI.Style.Red, true);
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 5, 5), GUIStyle.Red, true);
|
||||
}
|
||||
var bodyDrawPos = body.DrawPosition;
|
||||
bodyDrawPos.Y = -bodyDrawPos.Y;
|
||||
@@ -943,11 +945,11 @@ namespace Barotrauma
|
||||
var front = ConvertUnits.ToDisplayUnits(body.FarseerBody.GetWorldPoint(localFront));
|
||||
front.Y = -front.Y;
|
||||
GUI.DrawLine(spriteBatch, bodyDrawPos, front, Color.Yellow, width: 2);
|
||||
GUI.DrawLine(spriteBatch, from, to, GUI.Style.Red, width: 1);
|
||||
GUI.DrawLine(spriteBatch, from, to, GUIStyle.Red, width: 1);
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)from.X, (int)from.Y, 12, 12), Color.White, true);
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)to.X, (int)to.Y, 12, 12), Color.White, true);
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)from.X, (int)from.Y, 10, 10), Color.Blue, true);
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)to.X, (int)to.Y, 10, 10), GUI.Style.Red, true);
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)to.X, (int)to.Y, 10, 10), GUIStyle.Red, true);
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)front.X, (int)front.Y, 10, 10), Color.Yellow, true);
|
||||
|
||||
//Vector2 mainLimbFront = ConvertUnits.ToDisplayUnits(ragdoll.MainLimb.body.FarseerBody.GetWorldPoint(ragdoll.MainLimb.body.GetFrontLocal(MathHelper.ToRadians(limbParams.Orientation))));
|
||||
@@ -1046,8 +1048,8 @@ namespace Barotrauma
|
||||
//{
|
||||
// width = (int)Math.Round(width / cam.Zoom);
|
||||
//}
|
||||
//GUI.DrawLine(spriteBatch, startPos, startPos + Vector2.Normalize(up) * size, GUI.Style.Red, width: width);
|
||||
Color color = modifier.DamageMultiplier > 1 ? GUI.Style.Red : GUI.Style.Green;
|
||||
//GUI.DrawLine(spriteBatch, startPos, startPos + Vector2.Normalize(up) * size, GUIStyle.Red, width: width);
|
||||
Color color = modifier.DamageMultiplier > 1 ? GUIStyle.Red : GUIStyle.Green;
|
||||
float size = ConvertUnits.ToDisplayUnits(body.GetSize().Length() / 2);
|
||||
if (isScreenSpace)
|
||||
{
|
||||
@@ -1078,9 +1080,9 @@ namespace Barotrauma
|
||||
{
|
||||
wearable.Sprite.SourceRect = new Rectangle(CharacterInfo.CalculateOffset(sprite, wearable.SheetIndex.Value), sprite.SourceRect.Size);
|
||||
}
|
||||
else if (type == LimbType.Head && character.Info != null && character.Info.Head.SheetIndex.HasValue)
|
||||
else if (type == LimbType.Head && character.Info != null)
|
||||
{
|
||||
wearable.Sprite.SourceRect = new Rectangle(CharacterInfo.CalculateOffset(sprite, character.Info.Head.SheetIndex.Value.ToPoint()), sprite.SourceRect.Size);
|
||||
wearable.Sprite.SourceRect = new Rectangle(CharacterInfo.CalculateOffset(sprite, character.Info.Head.SheetIndex.ToPoint()), sprite.SourceRect.Size);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1134,11 +1136,11 @@ namespace Barotrauma
|
||||
{
|
||||
if (wearable.Type == WearableType.Hair)
|
||||
{
|
||||
wearableColor = character.Info.HairColor;
|
||||
wearableColor = character.Info.Head.HairColor;
|
||||
}
|
||||
else if (wearable.Type == WearableType.Beard || wearable.Type == WearableType.Moustache)
|
||||
{
|
||||
wearableColor = character.Info.FacialHairColor;
|
||||
wearableColor = character.Info.Head.FacialHairColor;
|
||||
}
|
||||
}
|
||||
float scale = wearable.Scale;
|
||||
@@ -1164,22 +1166,22 @@ namespace Barotrauma
|
||||
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)
|
||||
private WearableSprite GetWearableSprite(WearableType type)//, bool random = false)
|
||||
{
|
||||
var info = character.Info;
|
||||
if (info == null) { return null; }
|
||||
XElement element;
|
||||
if (random)
|
||||
ContentXElement element;
|
||||
/*if (random)
|
||||
{
|
||||
element = info.FilterByTypeAndHeadID(info.FilterElementsByGenderAndRace(info.Wearables, info.Gender, info.Race), type, info.Head.HeadSpriteId)?.GetRandom(Rand.RandSync.ClientOnly);
|
||||
element = info.FilterElements(info.Wearables, info.Head.Preset.TagSet)?.GetRandom(Rand.RandSync.ClientOnly);
|
||||
}
|
||||
else
|
||||
{
|
||||
element = info.FilterByTypeAndHeadID(info.FilterElementsByGenderAndRace(info.Wearables, info.Gender, info.Race), type, info.Head.HeadSpriteId)?.FirstOrDefault();
|
||||
}
|
||||
{*/
|
||||
element = info.FilterElements(info.Wearables, info.Head.Preset.TagSet, type)?.FirstOrDefault();
|
||||
//}
|
||||
if (element != null)
|
||||
{
|
||||
return new WearableSprite(element.Element("sprite"), type);
|
||||
return new WearableSprite(element.GetChildElement("sprite"), type);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.IO;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class ModProject
|
||||
{
|
||||
public class File
|
||||
{
|
||||
private File(string path, Type type)
|
||||
{
|
||||
Path = path.CleanUpPathCrossPlatform(correctFilenameCase: false);
|
||||
Type = type switch
|
||||
{
|
||||
_ when !type.IsSubclassOf(typeof(ContentFile)) => throw new ArgumentException($"{type.Name} does not derive from {nameof(ContentFile)}"),
|
||||
{ IsAbstract: true } => throw new ArgumentException($"{type.Name} is abstract"),
|
||||
_ => type
|
||||
};
|
||||
}
|
||||
|
||||
private File(ContentFile f)
|
||||
{
|
||||
Path = f.Path.RawValue ?? "";
|
||||
Type = f.GetType();
|
||||
}
|
||||
|
||||
public static File FromContentFile(ContentFile file)
|
||||
=> new File(file);
|
||||
|
||||
public static File FromPath<T>(string path) where T : ContentFile
|
||||
=> new File(path, typeof(T));
|
||||
|
||||
/// <summary>
|
||||
/// Prefer FromPath<T> when possible, this just exists
|
||||
/// for cases where the type can only be decided at runtime
|
||||
/// </summary>
|
||||
public static File FromPath(string path, Type type)
|
||||
=> new File(path, type);
|
||||
|
||||
public readonly string Path;
|
||||
public readonly Type Type;
|
||||
|
||||
public XElement ToXElement()
|
||||
{
|
||||
if (Type is null) { throw new InvalidOperationException("Type must be set before calling ToXElement"); }
|
||||
if (Path.IsNullOrEmpty()) { throw new InvalidOperationException("Path must be set before calling ToXElement"); }
|
||||
return new XElement(Type.Name.RemoveFromEnd("File"), new XAttribute("file", Path));
|
||||
}
|
||||
}
|
||||
|
||||
public ModProject() { }
|
||||
|
||||
public ModProject(ContentPackage? contentPackage)
|
||||
{
|
||||
if (contentPackage is null) { return; }
|
||||
Name = contentPackage.Name;
|
||||
AltNames = contentPackage.AltNames.ToList();
|
||||
files = contentPackage.Files.Select(File.FromContentFile).ToList();
|
||||
ModVersion = IncrementModVersion(contentPackage.ModVersion);
|
||||
IsCore = contentPackage is CorePackage;
|
||||
SteamWorkshopId = contentPackage.SteamWorkshopId;
|
||||
ExpectedHash = contentPackage.Hash;
|
||||
InstallTime = contentPackage.InstallTime;
|
||||
}
|
||||
|
||||
private string name = "";
|
||||
public string Name
|
||||
{
|
||||
get => name;
|
||||
set
|
||||
{
|
||||
var charsToRemove = Path.GetInvalidFileNameChars();
|
||||
name = string.Concat(value.Where(c => !charsToRemove.Contains(c)));
|
||||
}
|
||||
}
|
||||
|
||||
public readonly List<string> AltNames = new List<string>();
|
||||
|
||||
private readonly List<File> files = new List<File>();
|
||||
public IReadOnlyList<File> Files => files;
|
||||
|
||||
public string ModVersion = ContentPackage.DefaultModVersion;
|
||||
|
||||
public Md5Hash? ExpectedHash { get; private set; }
|
||||
|
||||
public bool IsCore = false;
|
||||
|
||||
public UInt64 SteamWorkshopId = 0;
|
||||
|
||||
public DateTime? InstallTime = null;
|
||||
|
||||
public bool HasFile(File file)
|
||||
=> Files.Any(f =>
|
||||
string.Equals(f.Path, file.Path, StringComparison.OrdinalIgnoreCase)
|
||||
&& f.Type == file.Type);
|
||||
|
||||
public void AddFile(File file)
|
||||
{
|
||||
if (!HasFile(file))
|
||||
{
|
||||
files.Add(file);
|
||||
DiscardHashAndInstallTime();
|
||||
}
|
||||
}
|
||||
|
||||
public void DiscardHashAndInstallTime()
|
||||
{
|
||||
ExpectedHash = null;
|
||||
InstallTime = null;
|
||||
}
|
||||
|
||||
public static string IncrementModVersion(string modVersion)
|
||||
{
|
||||
//look for an integer at the end of the string and increment it
|
||||
int startIndex = modVersion.Length - 1;
|
||||
while (char.IsDigit(modVersion[startIndex])) { startIndex--; }
|
||||
startIndex++;
|
||||
|
||||
if (startIndex >= modVersion.Length
|
||||
|| !char.IsDigit(modVersion[startIndex])
|
||||
|| !int.TryParse(
|
||||
modVersion[startIndex..],
|
||||
NumberStyles.Any,
|
||||
CultureInfo.InvariantCulture,
|
||||
out int theFinalInteger))
|
||||
{
|
||||
return modVersion;
|
||||
}
|
||||
|
||||
return $"{modVersion[..startIndex]}{(theFinalInteger + 1).ToString(CultureInfo.InvariantCulture)}";
|
||||
}
|
||||
|
||||
public XDocument ToXDocument()
|
||||
{
|
||||
XDocument doc = new XDocument();
|
||||
XElement rootElement = new XElement("contentpackage");
|
||||
|
||||
void addRootAttribute<T>(string name, T value) where T : notnull
|
||||
=> rootElement.Add(new XAttribute(name, value.ToString() ?? ""));
|
||||
|
||||
addRootAttribute("name", Name);
|
||||
addRootAttribute("modversion", ModVersion);
|
||||
addRootAttribute("corepackage", IsCore);
|
||||
if (SteamWorkshopId != 0) { addRootAttribute("steamworkshopid", SteamWorkshopId); }
|
||||
addRootAttribute("gameversion", GameMain.Version);
|
||||
if (AltNames.Any()) { addRootAttribute("altnames", string.Join(",", AltNames)); }
|
||||
if (ExpectedHash != null) { addRootAttribute("expectedhash", ExpectedHash.StringRepresentation); }
|
||||
if (InstallTime != null) { addRootAttribute("installtime", ToolBox.Epoch.FromDateTime(InstallTime.Value)); }
|
||||
|
||||
files.ForEach(f => rootElement.Add(f.ToXElement()));
|
||||
|
||||
doc.Add(rootElement);
|
||||
return doc;
|
||||
}
|
||||
|
||||
public void Save(string path)
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(path)!);
|
||||
ToXDocument().SaveSafe(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Barotrauma.IO;
|
||||
using Barotrauma.Steam;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public static partial class ContentPackageManager
|
||||
{
|
||||
public sealed partial class PackageSource : ICollection<ContentPackage>
|
||||
{
|
||||
public string SaveRegularMod(ModProject modProject)
|
||||
{
|
||||
if (modProject.IsCore) { throw new ArgumentException("ModProject must not be a core package"); }
|
||||
|
||||
string fileListPath = Path.Combine(directory, ToolBox.RemoveInvalidFileNameChars(modProject.Name), ContentPackage.FileListFileName)
|
||||
.CleanUpPathCrossPlatform(correctFilenameCase: false);
|
||||
modProject.Save(fileListPath);
|
||||
Refresh(); EnabledPackages.DisableRemovedMods();
|
||||
|
||||
return fileListPath;
|
||||
}
|
||||
|
||||
public RegularPackage GetRegularModByPath(string fileListPath)
|
||||
{
|
||||
return Regular.First(p => p.Path == fileListPath);
|
||||
}
|
||||
|
||||
public RegularPackage SaveAndEnableRegularMod(ModProject modProject)
|
||||
{
|
||||
string fileListPath = SaveRegularMod(modProject);
|
||||
var package = GetRegularModByPath(fileListPath);
|
||||
EnabledPackages.EnableRegular(package);
|
||||
|
||||
return package;
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<IEnumerable<Steamworks.Ugc.Item>> EnqueueWorkshopUpdates()
|
||||
{
|
||||
ISet<Steamworks.Ugc.Item> subscribedItems = await SteamManager.Workshop.GetAllSubscribedItems();
|
||||
|
||||
var needInstalling = subscribedItems.Where(item
|
||||
=> !WorkshopPackages.Any(p
|
||||
=> item.Id == p.SteamWorkshopId
|
||||
&& p.InstallTime.HasValue
|
||||
&& item.LatestUpdateTime <= p.InstallTime))
|
||||
.ToArray();
|
||||
if (needInstalling.Any())
|
||||
{
|
||||
await Task.WhenAll(
|
||||
needInstalling.Select(SteamManager.Workshop.DownloadModThenEnqueueInstall));
|
||||
}
|
||||
|
||||
return needInstalling;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,297 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Steam;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Directory = Barotrauma.IO.Directory;
|
||||
using File = Barotrauma.IO.File;
|
||||
using Path = Barotrauma.IO.Path;
|
||||
|
||||
namespace Barotrauma.Transition
|
||||
{
|
||||
/// <summary>
|
||||
/// Class dedicated to transitioning away from the old, shitty
|
||||
/// Mods + Submarines folders to the new LocalMods folder
|
||||
/// </summary>
|
||||
public static class UgcTransition
|
||||
{
|
||||
private const string readmeName = "LOCALMODS_README.txt";
|
||||
|
||||
public static void Prepare()
|
||||
{
|
||||
TaskPool.Add("UgcTransition.Prepare", DetermineItemsToTransition(), t =>
|
||||
{
|
||||
if (!t.TryGetResult(out (OldSubs, OldItemAssemblies, OldMods) result)) { return; }
|
||||
var (subs, itemAssemblies, mods) = result;
|
||||
if (!subs.FilePaths.Any() && !itemAssemblies.FilePaths.Any() && !mods.Mods.Any()) { return; }
|
||||
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("Ugc.TransferTitle"), "", relativeSize: (0.5f, 0.8f),
|
||||
buttons: new LocalizedString[] { TextManager.Get("Ugc.TransferButton") });
|
||||
|
||||
var desc = new GUITextBlock(new RectTransform((1.0f, 0.24f), msgBox.Content.RectTransform),
|
||||
text: TextManager.Get("Ugc.TransferDesc"), wrap: true, textAlignment: Alignment.CenterLeft);
|
||||
|
||||
var modsList = new GUIListBox(new RectTransform((1.0f, 0.6f), msgBox.Content.RectTransform))
|
||||
{
|
||||
HoverCursor = CursorState.Default
|
||||
};
|
||||
Dictionary<string, GUITickBox> pathTickboxMap = new Dictionary<string, GUITickBox>();
|
||||
|
||||
void addHeader(LocalizedString str)
|
||||
{
|
||||
var itemFrame = new GUITextBlock(new RectTransform((1.0f, 0.08f), modsList.Content.RectTransform),
|
||||
text: str, font: GUIStyle.SubHeadingFont)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
}
|
||||
void addTickbox(string dir, string name, bool ticked)
|
||||
{
|
||||
var itemFrame = new GUIFrame(new RectTransform((1.0f, 0.07f), modsList.Content.RectTransform),
|
||||
style: null)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
var tickbox = new GUITickBox(new RectTransform(Vector2.One, itemFrame.RectTransform), name)
|
||||
{
|
||||
Selected = ticked
|
||||
};
|
||||
pathTickboxMap.Add(dir, tickbox);
|
||||
}
|
||||
|
||||
bool firstHeader = true;
|
||||
|
||||
void addSpacer()
|
||||
{
|
||||
if (firstHeader) { firstHeader = false; return; }
|
||||
addHeader("");
|
||||
}
|
||||
|
||||
if (subs.FilePaths.Any())
|
||||
{
|
||||
addSpacer();
|
||||
addHeader(TextManager.Get("WorkshopLabelSubmarines"));
|
||||
foreach (var sub in subs.FilePaths)
|
||||
{
|
||||
var subName = Path.GetFileNameWithoutExtension(sub);
|
||||
addTickbox(sub, subName, ticked: !ContentPackageManager.LocalPackages.Any(p => p.NameMatches(subName)));
|
||||
}
|
||||
}
|
||||
|
||||
if (itemAssemblies.FilePaths.Any())
|
||||
{
|
||||
addSpacer();
|
||||
addHeader(TextManager.Get("ItemAssemblies"));
|
||||
foreach (var itemAssembly in itemAssemblies.FilePaths)
|
||||
{
|
||||
var assemblyName = Path.GetFileNameWithoutExtension(itemAssembly);
|
||||
addTickbox(itemAssembly, assemblyName, ticked: !ContentPackageManager.LocalPackages.Any(p => p.NameMatches(assemblyName)));
|
||||
}
|
||||
}
|
||||
|
||||
if (mods.Mods.Any())
|
||||
{
|
||||
addSpacer();
|
||||
addHeader(TextManager.Get("SubscribedMods"));
|
||||
foreach (var mod in mods.Mods)
|
||||
{
|
||||
addTickbox(mod.Dir, mod.Name, ticked: !ContentPackageManager.LocalPackages.Any(p => p.SteamWorkshopId != 0 && p.SteamWorkshopId == mod.Item?.Id));
|
||||
}
|
||||
}
|
||||
|
||||
GUIMessageBox? subMsgBox = null;
|
||||
|
||||
void createSubMsgBox(LocalizedString str, bool closable)
|
||||
{
|
||||
subMsgBox?.Close();
|
||||
subMsgBox = new GUIMessageBox(headerText: "", text: str,
|
||||
buttons: closable ? new[] { TextManager.Get("Close") } : Array.Empty<LocalizedString>());
|
||||
if (closable)
|
||||
{
|
||||
subMsgBox.Buttons[0].OnClicked = subMsgBox.Close;
|
||||
}
|
||||
}
|
||||
|
||||
msgBox.Buttons[0].OnClicked = (b, o) =>
|
||||
{
|
||||
TaskPool.Add("TransferMods", TransferMods(pathTickboxMap), t2 =>
|
||||
{
|
||||
if (t2.Exception != null)
|
||||
{
|
||||
DebugConsole.ThrowError("There was an error transferring mods", t2.Exception.GetInnermost());
|
||||
}
|
||||
ContentPackageManager.LocalPackages.Refresh();
|
||||
createSubMsgBox(TextManager.Get("Ugc.TransferComplete"), closable: true);
|
||||
});
|
||||
msgBox.Close();
|
||||
createSubMsgBox(TextManager.Get("Ugc.Transferring"), closable: false);
|
||||
return false;
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private struct OldSubs
|
||||
{
|
||||
public readonly IReadOnlyList<string> FilePaths;
|
||||
|
||||
public OldSubs(IReadOnlyList<string> filePaths)
|
||||
{
|
||||
FilePaths = filePaths;
|
||||
}
|
||||
}
|
||||
|
||||
private struct OldItemAssemblies
|
||||
{
|
||||
public readonly IReadOnlyList<string> FilePaths;
|
||||
|
||||
public OldItemAssemblies(IReadOnlyList<string> filePaths)
|
||||
{
|
||||
FilePaths = filePaths;
|
||||
}
|
||||
}
|
||||
|
||||
private struct OldMods
|
||||
{
|
||||
public readonly IReadOnlyList<(string Dir, string Name, Steamworks.Ugc.Item? Item, DateTime InstallTime)> Mods;
|
||||
|
||||
public OldMods(IReadOnlyList<(string Dir, string Name, Steamworks.Ugc.Item? Item, DateTime InstallTime)> mods)
|
||||
{
|
||||
Mods = mods;
|
||||
}
|
||||
}
|
||||
|
||||
private const string oldSubsPath = "Submarines";
|
||||
private const string oldModsPath = "Mods";
|
||||
private const string oldItemAssembliesPath = "ItemAssemblies";
|
||||
|
||||
private static async Task<(OldSubs Subs, OldItemAssemblies ItemAssemblies, OldMods Mods)> DetermineItemsToTransition()
|
||||
{
|
||||
string[] subs = Array.Empty<string>();
|
||||
string[] itemAssemblies = Array.Empty<string>();
|
||||
List<(string Dir, string Name, Steamworks.Ugc.Item? Item, DateTime InstallTime)> mods
|
||||
= new List<(string Dir, string Name, Steamworks.Ugc.Item? Item, DateTime InstallTime)>();
|
||||
if (FolderShouldBeTransitioned(oldModsPath))
|
||||
{
|
||||
string[] getFiles(string path, string pattern)
|
||||
=> Directory.Exists(path)
|
||||
? Directory.GetFiles(path, pattern, SearchOption.TopDirectoryOnly)
|
||||
: Array.Empty<string>();
|
||||
|
||||
subs = getFiles(oldSubsPath, "*.sub");
|
||||
itemAssemblies = getFiles(oldItemAssembliesPath, "*.xml");
|
||||
|
||||
string[] allOldMods = Directory.GetDirectories(oldModsPath, "*", SearchOption.TopDirectoryOnly);
|
||||
|
||||
var publishedItems = await SteamManager.Workshop.GetPublishedItems();
|
||||
foreach (var modDir in allOldMods)
|
||||
{
|
||||
var fileList = XMLExtensions.TryLoadXml(Path.Combine(modDir, ContentPackage.FileListFileName), out _);
|
||||
if (fileList?.Root is null) { continue; }
|
||||
|
||||
var oldId = fileList.Root.GetAttributeUInt64("steamworkshopid", 0);
|
||||
var updateTime = File.GetLastWriteTime(modDir).ToUniversalTime();
|
||||
var oldName = fileList.Root.GetAttributeString("name", "");
|
||||
|
||||
var item = oldId != 0 ? publishedItems.FirstOrNull(it => it.Id == oldId) : null;
|
||||
if (oldId == 0 || item.HasValue)
|
||||
{
|
||||
mods.Add((modDir, oldName, item, updateTime));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (!(Screen.Selected is MainMenuScreen)) { await Task.Delay(50); }
|
||||
|
||||
return (new OldSubs(subs), new OldItemAssemblies(itemAssemblies), new OldMods(mods));
|
||||
}
|
||||
|
||||
private static bool FolderShouldBeTransitioned(string folderName)
|
||||
{
|
||||
return Directory.Exists(folderName)
|
||||
&& !File.Exists(Path.Combine(folderName, readmeName));
|
||||
}
|
||||
|
||||
private static async Task TransferMods(Dictionary<string, GUITickBox> pathTickboxMap)
|
||||
{
|
||||
//WriteReadme(oldSubsPath); //can't do this because the old submarine discovery code is borked
|
||||
WriteReadme(oldModsPath);
|
||||
await Task.WhenAll(pathTickboxMap.Select(TransferMod));
|
||||
}
|
||||
|
||||
private static Task TransferMod(KeyValuePair<string, GUITickBox> kvp)
|
||||
=> TransferMod(kvp.Key, kvp.Value);
|
||||
|
||||
private static async Task TransferMod(string path, GUITickBox tickbox)
|
||||
{
|
||||
if (!tickbox.Selected) { return; }
|
||||
string dirName = Path.GetFileNameWithoutExtension(path);
|
||||
string destPath = Path.Combine(ContentPackage.LocalModsDir, dirName);
|
||||
|
||||
//find unique path to save in
|
||||
for (int i = 0;;i++)
|
||||
{
|
||||
if (!Directory.Exists(destPath)) { break; }
|
||||
destPath = Path.Combine(ContentPackage.LocalModsDir, $"{dirName}.{i}");
|
||||
}
|
||||
|
||||
bool isSub = path.StartsWith(oldSubsPath, StringComparison.OrdinalIgnoreCase);
|
||||
bool isItemAssembly = path.StartsWith(oldItemAssembliesPath, StringComparison.OrdinalIgnoreCase);
|
||||
if (isSub || isItemAssembly)
|
||||
{
|
||||
//copying a sub or item assembly: manually create filelist.xml
|
||||
ModProject modProject = new ModProject
|
||||
{
|
||||
Name = dirName,
|
||||
ModVersion = ContentPackage.DefaultModVersion
|
||||
};
|
||||
|
||||
Type fileType;
|
||||
if (isSub)
|
||||
{
|
||||
fileType = typeof(SubmarineFile);
|
||||
XDocument? doc = SubmarineInfo.OpenFile(path, out _);
|
||||
if (doc?.Root != null)
|
||||
{
|
||||
SubmarineType subType = doc.Root.GetAttributeEnum("type", SubmarineType.Player);
|
||||
fileType = SubEditorScreen.DetermineSubFileType(subType);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fileType = typeof(ItemAssemblyFile);
|
||||
}
|
||||
|
||||
modProject.AddFile(ModProject.File.FromPath(
|
||||
Path.Combine(ContentPath.ModDirStr, $"{dirName}.{(isSub ? "sub" : "xml")}"),
|
||||
fileType));
|
||||
|
||||
Directory.CreateDirectory(destPath);
|
||||
File.Copy(path, Path.Combine(destPath, $"{dirName}.{(isSub ? "sub" : "xml")}"));
|
||||
modProject.Save(Path.Combine(destPath, ContentPackage.FileListFileName));
|
||||
|
||||
await Task.Yield();
|
||||
}
|
||||
else
|
||||
{
|
||||
//copying a mod: we have a neat method for that!
|
||||
await SteamManager.Workshop.CopyDirectory(path, Path.GetFileName(path), path, destPath);
|
||||
}
|
||||
}
|
||||
|
||||
private static void WriteReadme(string folderName)
|
||||
{
|
||||
if (!Directory.Exists(folderName)) { return; }
|
||||
File.WriteAllText(path: Path.Combine(folderName, readmeName),
|
||||
contents: "This folder is no longer used by Barotrauma;\n" +
|
||||
"your mods and submarines should have been transferred\n" +
|
||||
"to LocalMods. If they are not being found, delete this\n" +
|
||||
"readme and relaunch the game.", encoding: Encoding.UTF8);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -94,7 +94,7 @@ namespace Barotrauma
|
||||
|
||||
var (relative, min) = GetSizes(dialogType);
|
||||
|
||||
GUIMessageBox messageBox = new GUIMessageBox(string.Empty, string.Empty, new string[0],
|
||||
GUIMessageBox messageBox = new GUIMessageBox(string.Empty, string.Empty, Array.Empty<LocalizedString>(),
|
||||
relativeSize: relative, minSize: min,
|
||||
type: GUIMessageBox.Type.InGame, backgroundIcon: EventSet.GetEventSprite(spriteIdentifier))
|
||||
{
|
||||
@@ -105,7 +105,7 @@ namespace Barotrauma
|
||||
|
||||
messageBox.InnerFrame.ClearChildren();
|
||||
messageBox.AutoClose = false;
|
||||
GUI.Style.Apply(messageBox.InnerFrame, "DialogBox");
|
||||
GUIStyle.Apply(messageBox.InnerFrame, "DialogBox");
|
||||
|
||||
if (actionInstance != null)
|
||||
{
|
||||
@@ -222,11 +222,11 @@ namespace Barotrauma
|
||||
closeButton.SlideIn(0.5f, 0.33f, 16, SlideDirection.Down);
|
||||
|
||||
InputType? closeInput = null;
|
||||
if (GameMain.Config.KeyBind(InputType.Use).MouseButton == MouseButton.None)
|
||||
if (GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Use].MouseButton == MouseButton.None)
|
||||
{
|
||||
closeInput = InputType.Use;
|
||||
}
|
||||
else if (GameMain.Config.KeyBind(InputType.Select).MouseButton == MouseButton.None)
|
||||
else if (GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Select].MouseButton == MouseButton.None)
|
||||
{
|
||||
closeInput = InputType.Select;
|
||||
}
|
||||
@@ -239,7 +239,7 @@ namespace Barotrauma
|
||||
{
|
||||
GUIButton btn = component as GUIButton;
|
||||
btn?.OnClicked(btn, btn.UserData);
|
||||
btn?.Flash(GUI.Style.Green);
|
||||
btn?.Flash(GUIStyle.Green);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -308,7 +308,7 @@ namespace Barotrauma
|
||||
AlwaysOverrideCursor = true
|
||||
};
|
||||
|
||||
string translatedText = TextManager.Get(text, returnNull: true) ?? text;
|
||||
LocalizedString translatedText = TextManager.Get(text);
|
||||
|
||||
if (speaker?.Info != null && drawChathead)
|
||||
{
|
||||
@@ -335,9 +335,9 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (string option in options)
|
||||
{
|
||||
var btn = new GUIButton(new RectTransform(new Vector2(0.9f, 0.01f), textContent.RectTransform), TextManager.Get(option, returnNull: true) ?? option, style: "ListBoxElement");
|
||||
var btn = new GUIButton(new RectTransform(new Vector2(0.9f, 0.01f), textContent.RectTransform), TextManager.Get(option), style: "ListBoxElement");
|
||||
btn.TextBlock.TextAlignment = Alignment.CenterLeft;
|
||||
btn.TextColor = btn.HoverTextColor = GUI.Style.Green;
|
||||
btn.TextColor = btn.HoverTextColor = GUIStyle.Green;
|
||||
btn.TextBlock.Wrap = true;
|
||||
buttons.Add(btn);
|
||||
}
|
||||
@@ -384,7 +384,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
// Too broken, left it here if I ever want to come back to it
|
||||
private static List<RichTextData> GetQuoteHighlights(string text, Color color)
|
||||
/*private static List<RichTextData> GetQuoteHighlights(string text, Color color)
|
||||
{
|
||||
char[] quotes = { '“', '”', '\"', '\'', '「', '」'};
|
||||
|
||||
@@ -406,6 +406,6 @@ namespace Barotrauma
|
||||
last.EndIndex = text.Length;
|
||||
}
|
||||
return textColors;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
@@ -34,7 +35,7 @@ namespace Barotrauma
|
||||
|
||||
var textOffset = new Vector2(-150, 0);
|
||||
spriteBatch.DrawCircle(drawPos, 600, 6, Color.White, thickness: 20);
|
||||
GUI.DrawString(spriteBatch, drawPos + textOffset, ev.ToString(), Color.White, Color.Black, 0, GUI.LargeFont);
|
||||
GUI.DrawString(spriteBatch, drawPos + textOffset, ev.ToString(), Color.White, Color.Black, 0, GUIStyle.LargeFont);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,24 +47,23 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
float theoreticalMaxMonsterStrength = 10000;
|
||||
float relativeMaxMonsterStrength = theoreticalMaxMonsterStrength * GameMain.GameSession.LevelData.Difficulty / 100;
|
||||
float relativeMaxMonsterStrength = theoreticalMaxMonsterStrength * (GameMain.GameSession?.LevelData?.Difficulty ?? 0f) / 100;
|
||||
float absoluteMonsterStrength = monsterStrength / theoreticalMaxMonsterStrength;
|
||||
float relativeMonsterStrength = monsterStrength / relativeMaxMonsterStrength;
|
||||
GUI.DrawString(spriteBatch, new Vector2(10, y), "EventManager", Color.White, Color.Black * 0.6f, 0, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(15, y + 20), "Event cooldown: " + (int)Math.Max(eventCoolDown, 0), Color.White, Color.Black * 0.6f, 0, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(15, y + 35), "Current intensity: " + (int)Math.Round(currentIntensity * 100), Color.Lerp(Color.White, GUI.Style.Red, currentIntensity), Color.Black * 0.6f, 0, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(15, y + 50), "Target intensity: " + (int)Math.Round(targetIntensity * 100), Color.Lerp(Color.White, GUI.Style.Red, targetIntensity), Color.Black * 0.6f, 0, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(10, y), "EventManager", Color.White, Color.Black * 0.6f, 0, GUIStyle.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(15, y + 20), "Event cooldown: " + (int)Math.Max(eventCoolDown, 0), Color.White, Color.Black * 0.6f, 0, GUIStyle.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(15, y + 35), "Current intensity: " + (int)Math.Round(currentIntensity * 100), Color.Lerp(Color.White, GUIStyle.Red, currentIntensity), Color.Black * 0.6f, 0, GUIStyle.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(15, y + 50), "Target intensity: " + (int)Math.Round(targetIntensity * 100), Color.Lerp(Color.White, GUIStyle.Red, targetIntensity), Color.Black * 0.6f, 0, GUIStyle.SmallFont);
|
||||
|
||||
GUI.DrawString(spriteBatch, new Vector2(15, y + 65), "Crew health: " + (int)Math.Round(avgCrewHealth * 100), Color.Lerp(GUI.Style.Red, GUI.Style.Green, avgCrewHealth), Color.Black * 0.6f, 0, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(15, y + 80), "Hull integrity: " + (int)Math.Round(avgHullIntegrity * 100), Color.Lerp(GUI.Style.Red, GUI.Style.Green, avgHullIntegrity), Color.Black * 0.6f, 0, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(15, y + 95), "Flooding amount: " + (int)Math.Round(floodingAmount * 100), Color.Lerp(GUI.Style.Green, GUI.Style.Red, floodingAmount), Color.Black * 0.6f, 0, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(15, y + 110), "Fire amount: " + (int)Math.Round(fireAmount * 100), Color.Lerp(GUI.Style.Green, GUI.Style.Red, fireAmount), Color.Black * 0.6f, 0, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(15, y + 125), "Enemy danger: " + (int)Math.Round(enemyDanger * 100), Color.Lerp(GUI.Style.Green, GUI.Style.Red, enemyDanger), Color.Black * 0.6f, 0, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(15, y + 140), "Current monster strength (total): " + (int)Math.Round(monsterStrength), Color.Lerp(GUI.Style.Green, GUI.Style.Red, relativeMonsterStrength), Color.Black * 0.6f, 0, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(15, y + 155), "Main events: " + (int)Math.Round(CumulativeMonsterStrengthMain), Color.White, Color.Black * 0.6f, 0, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(15, y + 170), "Ruin events: " + (int)Math.Round(CumulativeMonsterStrengthRuins), Color.White, Color.Black * 0.6f, 0, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(15, y + 185), "Wreck events: " + (int)Math.Round(CumulativeMonsterStrengthWrecks), Color.White, Color.Black * 0.6f, 0, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(15, y + 200), "Cave events: " + (int)Math.Round(CumulativeMonsterStrengthCaves), Color.White, Color.Black * 0.6f, 0, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(15, y + 65), "Crew health: " + (int)Math.Round(avgCrewHealth * 100), Color.Lerp(GUIStyle.Red, GUIStyle.Green, avgCrewHealth), Color.Black * 0.6f, 0, GUIStyle.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(15, y + 80), "Hull integrity: " + (int)Math.Round(avgHullIntegrity * 100), Color.Lerp(GUIStyle.Red, GUIStyle.Green, avgHullIntegrity), Color.Black * 0.6f, 0, GUIStyle.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(15, y + 95), "Flooding amount: " + (int)Math.Round(floodingAmount * 100), Color.Lerp(GUIStyle.Green, GUIStyle.Red, floodingAmount), Color.Black * 0.6f, 0, GUIStyle.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(15, y + 110), "Fire amount: " + (int)Math.Round(fireAmount * 100), Color.Lerp(GUIStyle.Green, GUIStyle.Red, fireAmount), Color.Black * 0.6f, 0, GUIStyle.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(15, y + 125), "Enemy danger: " + (int)Math.Round(enemyDanger * 100), Color.Lerp(GUIStyle.Green, GUIStyle.Red, enemyDanger), Color.Black * 0.6f, 0, GUIStyle.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(15, y + 140), "Current monster strength (total): " + (int)Math.Round(monsterStrength), Color.Lerp(GUIStyle.Green, GUIStyle.Red, relativeMonsterStrength), Color.Black * 0.6f, 0, GUIStyle.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(15, y + 155), "Main events: " + (int)Math.Round(CumulativeMonsterStrengthMain), Color.White, Color.Black * 0.6f, 0, GUIStyle.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(15, y + 170), "Ruin events: " + (int)Math.Round(CumulativeMonsterStrengthRuins), Color.White, Color.Black * 0.6f, 0, GUIStyle.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(15, y + 185), "Wreck events: " + (int)Math.Round(CumulativeMonsterStrengthWrecks), Color.White, Color.Black * 0.6f, 0, GUIStyle.SmallFont);
|
||||
|
||||
#if DEBUG
|
||||
if (PlayerInput.KeyDown(Microsoft.Xna.Framework.Input.Keys.LeftAlt) &&
|
||||
@@ -101,7 +101,7 @@ namespace Barotrauma
|
||||
{
|
||||
isGraphSelected = false;
|
||||
}
|
||||
Color intensityColor = Color.Lerp(Color.White, GUI.Style.Red, currentIntensity);
|
||||
Color intensityColor = Color.Lerp(Color.White, GUIStyle.Red, currentIntensity);
|
||||
if (isGraphHovered || isGraphSelected)
|
||||
{
|
||||
graphRect.Size = new Point(GameMain.GraphicsWidth - 30, (int)(GameMain.GraphicsHeight * 0.35f));
|
||||
@@ -122,7 +122,7 @@ namespace Barotrauma
|
||||
{
|
||||
height *= 3;
|
||||
string text = (order / 6).ToString();
|
||||
var font = GUI.SmallFont;
|
||||
var font = GUIStyle.SmallFont;
|
||||
Vector2 textSize = font.MeasureString(text);
|
||||
Vector2 textPos = new Vector2(bottomPoint.X - textSize.X / 2, bottomPoint.Y + height * 1.5f);
|
||||
GUI.DrawString(sBatch, textPos, text, Color.White, font: font);
|
||||
@@ -175,23 +175,23 @@ namespace Barotrauma
|
||||
int x = graphRect.X;
|
||||
if (isCrewAway && crewAwayDuration < settings.FreezeDurationWhenCrewAway)
|
||||
{
|
||||
GUI.DrawString(spriteBatch, new Vector2(x, y), "Events frozen (crew away from sub): " + ToolBox.SecondsToReadableTime(settings.FreezeDurationWhenCrewAway - crewAwayDuration), Color.LightGreen * 0.8f, null, 0, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(x, y), "Events frozen (crew away from sub): " + ToolBox.SecondsToReadableTime(settings.FreezeDurationWhenCrewAway - crewAwayDuration), Color.LightGreen * 0.8f, null, 0, GUIStyle.SmallFont);
|
||||
y += 15;
|
||||
}
|
||||
else if (crewAwayResetTimer > 0.0f)
|
||||
{
|
||||
GUI.DrawString(spriteBatch, new Vector2(x, y), "Events frozen (crew just returned to the sub): " + ToolBox.SecondsToReadableTime(crewAwayResetTimer), Color.LightGreen * 0.8f, null, 0, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(x, y), "Events frozen (crew just returned to the sub): " + ToolBox.SecondsToReadableTime(crewAwayResetTimer), Color.LightGreen * 0.8f, null, 0, GUIStyle.SmallFont);
|
||||
y += 15;
|
||||
}
|
||||
else if (eventCoolDown > 0.0f)
|
||||
{
|
||||
GUI.DrawString(spriteBatch, new Vector2(x, y), "Event cooldown active: " + ToolBox.SecondsToReadableTime(eventCoolDown), Color.LightGreen * 0.8f, null, 0, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(x, y), "Event cooldown active: " + ToolBox.SecondsToReadableTime(eventCoolDown), Color.LightGreen * 0.8f, null, 0, GUIStyle.SmallFont);
|
||||
y += 15;
|
||||
}
|
||||
else if (currentIntensity > eventThreshold)
|
||||
{
|
||||
GUI.DrawString(spriteBatch, new Vector2(x, y),
|
||||
"Intensity too high for new events: " + (int)(currentIntensity * 100) + "%/" + (int)(eventThreshold * 100) + "%", Color.LightGreen * 0.8f, null, 0, GUI.SmallFont);
|
||||
"Intensity too high for new events: " + (int)(currentIntensity * 100) + "%/" + (int)(eventThreshold * 100) + "%", Color.LightGreen * 0.8f, null, 0, GUIStyle.SmallFont);
|
||||
y += 15;
|
||||
}
|
||||
|
||||
@@ -199,29 +199,29 @@ namespace Barotrauma
|
||||
{
|
||||
if (Submarine.MainSub == null) { break; }
|
||||
|
||||
GUI.DrawString(spriteBatch, new Vector2(x, y), "New event (ID " + eventSet.DebugIdentifier + ") after: ", Color.Orange * 0.8f, null, 0, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(x, y), "New event (ID " + eventSet.Identifier + ") after: ", Color.Orange * 0.8f, null, 0, GUIStyle.SmallFont);
|
||||
y += 12;
|
||||
|
||||
if (eventSet.PerCave)
|
||||
{
|
||||
GUI.DrawString(spriteBatch, new Vector2(x, y), " submarine near cave", Color.Orange * 0.8f, null, 0, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(x, y), " submarine near cave", Color.Orange * 0.8f, null, 0, GUIStyle.SmallFont);
|
||||
y += 12;
|
||||
}
|
||||
if (eventSet.PerWreck)
|
||||
{
|
||||
GUI.DrawString(spriteBatch, new Vector2(x, y), " submarine near the wreck", Color.Orange * 0.8f, null, 0, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(x, y), " submarine near the wreck", Color.Orange * 0.8f, null, 0, GUIStyle.SmallFont);
|
||||
y += 12;
|
||||
}
|
||||
if (eventSet.PerRuin)
|
||||
{
|
||||
GUI.DrawString(spriteBatch, new Vector2(x, y), " submarine near the ruins", Color.Orange * 0.8f, null, 0, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(x, y), " submarine near the ruins", Color.Orange * 0.8f, null, 0, GUIStyle.SmallFont);
|
||||
y += 12;
|
||||
}
|
||||
if (roundDuration < eventSet.MinMissionTime)
|
||||
{
|
||||
GUI.DrawString(spriteBatch, new Vector2(x, y),
|
||||
" " + (int) (eventSet.MinDistanceTraveled * 100.0f) + "% travelled (current: " + (int) (distanceTraveled * 100.0f) + " %)",
|
||||
((Submarine.MainSub == null || distanceTraveled < eventSet.MinDistanceTraveled) ? Color.Lerp(GUI.Style.Yellow, GUI.Style.Red, eventSet.MinDistanceTraveled - distanceTraveled) : GUI.Style.Green) * 0.8f, null, 0, GUI.SmallFont);
|
||||
((Submarine.MainSub == null || distanceTraveled < eventSet.MinDistanceTraveled) ? Color.Lerp(GUIStyle.Yellow, GUIStyle.Red, eventSet.MinDistanceTraveled - distanceTraveled) : GUIStyle.Green) * 0.8f, null, 0, GUIStyle.SmallFont);
|
||||
y += 12;
|
||||
}
|
||||
|
||||
@@ -229,15 +229,15 @@ namespace Barotrauma
|
||||
{
|
||||
GUI.DrawString(spriteBatch, new Vector2(x, y),
|
||||
" intensity between " + eventSet.MinIntensity.FormatDoubleDecimal() + " and " + eventSet.MaxIntensity.FormatDoubleDecimal(),
|
||||
Color.Orange * 0.8f, null, 0, GUI.SmallFont);
|
||||
y += 12;
|
||||
Color.Orange * 0.8f, null, 0, GUIStyle.SmallFont);
|
||||
y += 12;
|
||||
}
|
||||
|
||||
if (roundDuration < eventSet.MinMissionTime)
|
||||
{
|
||||
GUI.DrawString(spriteBatch, new Vector2(x, y),
|
||||
" " + (int) (eventSet.MinMissionTime - roundDuration) + " s",
|
||||
Color.Lerp(GUI.Style.Yellow, GUI.Style.Red, (eventSet.MinMissionTime - roundDuration)), null, 0, GUI.SmallFont);
|
||||
Color.Lerp(GUIStyle.Yellow, GUIStyle.Red, (eventSet.MinMissionTime - roundDuration)), null, 0, GUIStyle.SmallFont);
|
||||
}
|
||||
|
||||
y += 15;
|
||||
@@ -249,14 +249,14 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
GUI.DrawString(spriteBatch, new Vector2(x, y), "Current events: ", Color.White * 0.9f, null, 0, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(x, y), "Current events: ", Color.White * 0.9f, null, 0, GUIStyle.SmallFont);
|
||||
y += yStep;
|
||||
|
||||
foreach (Event ev in activeEvents.Where(ev => !ev.IsFinished || PlayerInput.IsShiftDown()))
|
||||
{
|
||||
GUI.DrawString(spriteBatch, new Vector2(x + 5, y), ev.ToString(), (!ev.IsFinished ? Color.White : Color.Red) * 0.8f, null, 0, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(x + 5, y), ev.ToString(), (!ev.IsFinished ? Color.White : Color.Red) * 0.8f, null, 0, GUIStyle.SmallFont);
|
||||
|
||||
Rectangle rect = new Rectangle(new Point(x + 5, y), GUI.SmallFont.MeasureString(ev.ToString()).ToPoint());
|
||||
Rectangle rect = new Rectangle(new Point(x + 5, y), GUIStyle.SmallFont.MeasureString(ev.ToString()).ToPoint());
|
||||
|
||||
Rectangle outlineRect = new Rectangle(rect.Location, rect.Size);
|
||||
outlineRect.Inflate(4, 4);
|
||||
@@ -331,8 +331,8 @@ namespace Barotrauma
|
||||
if (Screen.Selected is GameScreen screen)
|
||||
{
|
||||
Camera cam = screen.Cam;
|
||||
Dictionary<Entity, List<string>> tagsDictionary = new Dictionary<Entity, List<string>>();
|
||||
foreach ((string key, List<Entity> value) in scriptedEvent.Targets)
|
||||
Dictionary<Entity, List<Identifier>> tagsDictionary = new Dictionary<Entity, List<Identifier>>();
|
||||
foreach ((Identifier key, List<Entity> value) in scriptedEvent.Targets)
|
||||
{
|
||||
foreach (Entity entity in value)
|
||||
{
|
||||
@@ -342,24 +342,24 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
tagsDictionary.Add(entity, new List<string> { key });
|
||||
tagsDictionary.Add(entity, new List<Identifier> { key });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string identifier = scriptedEvent.Prefab.Identifier;
|
||||
Identifier identifier = scriptedEvent.Prefab.Identifier;
|
||||
|
||||
foreach ((Entity entity, List<string> tags) in tagsDictionary)
|
||||
foreach ((Entity entity, List<Identifier> tags) in tagsDictionary)
|
||||
{
|
||||
if (entity.Removed) { continue; }
|
||||
|
||||
string text = tags.Aggregate("Tags:\n", (current, tag) => current + $" {tag.ColorizeObject()}\n").TrimEnd('\r', '\n');
|
||||
if (!string.IsNullOrWhiteSpace(identifier)) { text = $"Event: {identifier.ColorizeObject()}\n{text}"; }
|
||||
if (!identifier.IsEmpty) { text = $"Event: {identifier.ColorizeObject()}\n{text}"; }
|
||||
|
||||
List<RichTextData> richTextData = RichTextData.GetRichTextData(text, out text);
|
||||
ImmutableArray<RichTextData>? richTextData = RichTextData.GetRichTextData(text, out text);
|
||||
|
||||
Vector2 entityPos = cam.WorldToScreen(entity.WorldPosition);
|
||||
Vector2 infoSize = GUI.SmallFont.MeasureString(text);
|
||||
Vector2 infoSize = GUIStyle.SmallFont.MeasureString(text);
|
||||
|
||||
Vector2 infoPos = entityPos + new Vector2(128 * cam.Zoom, -(128 * cam.Zoom));
|
||||
infoPos.Y -= infoSize.Y / 2;
|
||||
@@ -370,7 +370,7 @@ namespace Barotrauma
|
||||
GUI.DrawRectangle(spriteBatch, infoRect, Color.Black * 0.8f, isFilled: true);
|
||||
GUI.DrawRectangle(spriteBatch, infoRect, Color.White, isFilled: false);
|
||||
|
||||
GUI.DrawStringWithColors(spriteBatch, infoPos, text, Color.White, richTextData, font: GUI.SmallFont);
|
||||
GUI.DrawStringWithColors(spriteBatch, infoPos, text, Color.White, richTextData, font: GUIStyle.SmallFont);
|
||||
|
||||
GUI.DrawLine(spriteBatch, entityPos, new Vector2(infoRect.Location.X, infoRect.Location.Y + infoRect.Height / 2), Color.White);
|
||||
}
|
||||
@@ -489,15 +489,15 @@ namespace Barotrauma
|
||||
{
|
||||
text = text.TrimEnd('\r', '\n');
|
||||
|
||||
string identifier = @event.Prefab.Identifier;
|
||||
if (!string.IsNullOrWhiteSpace(identifier))
|
||||
Identifier identifier = @event.Prefab.Identifier;
|
||||
if (!identifier.IsEmpty)
|
||||
{
|
||||
text = $"Identifier: {identifier.ColorizeObject()}\n{text}";
|
||||
}
|
||||
|
||||
List<RichTextData> richTextData = RichTextData.GetRichTextData(text, out text);
|
||||
ImmutableArray<RichTextData>? richTextData = RichTextData.GetRichTextData(text, out text);
|
||||
|
||||
Vector2 size = GUI.SmallFont.MeasureString(text);
|
||||
Vector2 size = GUIStyle.SmallFont.MeasureString(text);
|
||||
Vector2 pos = pinnedPosition;
|
||||
Rectangle infoRect;
|
||||
Rectangle? infoBarRect = null;
|
||||
@@ -520,7 +520,7 @@ namespace Barotrauma
|
||||
const string titleHeader = "Pinned event";
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, barRect, Color.DarkGray * 0.8f, isFilled: true);
|
||||
GUI.DrawString(spriteBatch, barRect.Location.ToVector2() + barRect.Size.ToVector2() / 2 - GUI.SubHeadingFont.MeasureString(titleHeader) / 2, titleHeader, Color.White);
|
||||
GUI.DrawString(spriteBatch, barRect.Location.ToVector2() + barRect.Size.ToVector2() / 2 - GUIStyle.SubHeadingFont.MeasureString(titleHeader) / 2, titleHeader, Color.White);
|
||||
GUI.DrawRectangle(spriteBatch, barRect, Color.White);
|
||||
infoBarRect = barRect;
|
||||
}
|
||||
@@ -546,8 +546,14 @@ namespace Barotrauma
|
||||
GUI.DrawRectangle(spriteBatch, infoRect, Color.Black * 0.8f, isFilled: true);
|
||||
GUI.DrawRectangle(spriteBatch, infoRect, Color.White);
|
||||
|
||||
GUI.DrawStringWithColors(spriteBatch, pos, text, Color.White, richTextData, null, 0, GUI.SmallFont);
|
||||
richTextData.Clear();
|
||||
if (richTextData.HasValue && richTextData.Value.Length > 0)
|
||||
{
|
||||
GUI.DrawStringWithColors(spriteBatch, pos, text, Color.White, richTextData.Value, null, 0, GUIStyle.SmallFont);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.DrawString(spriteBatch, pos, text, Color.White, null, 0, GUIStyle.SmallFont);
|
||||
}
|
||||
return infoBarRect ?? infoRect;
|
||||
}
|
||||
|
||||
@@ -557,7 +563,7 @@ namespace Barotrauma
|
||||
switch (eventType)
|
||||
{
|
||||
case NetworkEventType.STATUSEFFECT:
|
||||
string eventIdentifier = msg.ReadString();
|
||||
Identifier eventIdentifier = msg.ReadIdentifier();
|
||||
UInt16 actionIndex = msg.ReadUInt16();
|
||||
UInt16 targetCount = msg.ReadUInt16();
|
||||
List<Entity> targets = new List<Entity>();
|
||||
@@ -571,14 +577,14 @@ namespace Barotrauma
|
||||
var eventPrefab = EventSet.GetEventPrefab(eventIdentifier);
|
||||
if (eventPrefab == null) { return; }
|
||||
int j = 0;
|
||||
foreach (XElement element in eventPrefab.ConfigElement.Descendants())
|
||||
foreach (var element in eventPrefab.ConfigElement.Descendants())
|
||||
{
|
||||
if (j != actionIndex)
|
||||
{
|
||||
j++;
|
||||
continue;
|
||||
}
|
||||
foreach (XElement subElement in element.Elements())
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
if (!subElement.Name.ToString().Equals("statuseffect", StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||
StatusEffect effect = StatusEffect.Load(subElement, $"EventManager.ClientRead ({eventIdentifier})");
|
||||
@@ -633,13 +639,13 @@ namespace Barotrauma
|
||||
}
|
||||
break;
|
||||
case NetworkEventType.MISSION:
|
||||
string missionIdentifier = msg.ReadString();
|
||||
Identifier missionIdentifier = msg.ReadIdentifier();
|
||||
|
||||
MissionPrefab? prefab = MissionPrefab.List.Find(mp => mp.Identifier.Equals(missionIdentifier, StringComparison.OrdinalIgnoreCase));
|
||||
MissionPrefab? prefab = MissionPrefab.Prefabs.Find(mp => mp.Identifier == missionIdentifier);
|
||||
if (prefab != null)
|
||||
{
|
||||
new GUIMessageBox(string.Empty, TextManager.GetWithVariable("missionunlocked", "[missionname]", prefab.Name),
|
||||
new string[0], type: GUIMessageBox.Type.InGame, icon: prefab.Icon, relativeSize: new Vector2(0.3f, 0.15f), minSize: new Point(512, 128))
|
||||
Array.Empty<LocalizedString>(), type: GUIMessageBox.Type.InGame, icon: prefab.Icon, relativeSize: new Vector2(0.3f, 0.15f), minSize: new Point(512, 128))
|
||||
{
|
||||
IconColor = prefab.IconColor
|
||||
};
|
||||
@@ -657,7 +663,7 @@ namespace Barotrauma
|
||||
{
|
||||
GameMain.GameSession.Map.Connections[connectionIndex].Locked = false;
|
||||
new GUIMessageBox(string.Empty, TextManager.Get("pathunlockedgeneric"),
|
||||
new string[0], type: GUIMessageBox.Type.InGame, iconStyle: "UnlockPathIcon", relativeSize: new Vector2(0.3f, 0.15f), minSize: new Point(512, 128));
|
||||
Array.Empty<LocalizedString>(), type: GUIMessageBox.Type.InGame, iconStyle: "UnlockPathIcon", relativeSize: new Vector2(0.3f, 0.15f), minSize: new Point(512, 128));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Barotrauma
|
||||
if (state != value)
|
||||
{
|
||||
base.State = value;
|
||||
if (state == HostagesKilledState && !string.IsNullOrEmpty(hostagesKilledMessage))
|
||||
if (state == HostagesKilledState && !hostagesKilledMessage.IsNullOrEmpty())
|
||||
{
|
||||
CreateMessageBox(string.Empty, hostagesKilledMessage);
|
||||
}
|
||||
|
||||
@@ -8,23 +8,29 @@ namespace Barotrauma
|
||||
public override bool DisplayAsCompleted => false;
|
||||
public override bool DisplayAsFailed => false;
|
||||
|
||||
public override string GetMissionRewardText(Submarine sub)
|
||||
public override RichString GetMissionRewardText(Submarine sub)
|
||||
{
|
||||
string rewardText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", GetReward(sub)));
|
||||
LocalizedString rewardText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", GetReward(sub)));
|
||||
|
||||
LocalizedString retVal;
|
||||
if (rewardPerCrate.HasValue)
|
||||
{
|
||||
string rewardPerCrateText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", rewardPerCrate.Value));
|
||||
return TextManager.GetWithVariables("missionrewardcargopercrate",
|
||||
new string[] { "[rewardpercrate]", "[itemcount]", "[maxitemcount]", "[totalreward]" },
|
||||
new string[] { rewardPerCrateText, itemsToSpawn.Count.ToString(), maxItemCount.ToString(), $"‖color:gui.orange‖{rewardText}‖end‖" });
|
||||
LocalizedString rewardPerCrateText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", rewardPerCrate.Value));
|
||||
retVal = TextManager.GetWithVariables("missionrewardcargopercrate",
|
||||
("[rewardpercrate]", rewardPerCrateText),
|
||||
("[itemcount]", itemsToSpawn.Count.ToString()),
|
||||
("[maxitemcount]", maxItemCount.ToString()),
|
||||
("[totalreward]", $"‖color:gui.orange‖{rewardText}‖end‖"));
|
||||
}
|
||||
else
|
||||
{
|
||||
return TextManager.GetWithVariables("missionrewardcargo",
|
||||
new string[] { "[totalreward]", "[itemcount]", "[maxitemcount]" },
|
||||
new string[] { $"‖color:gui.orange‖{rewardText}‖end‖", itemsToSpawn.Count.ToString(), maxItemCount.ToString() });
|
||||
retVal = TextManager.GetWithVariables("missionrewardcargo",
|
||||
("[totalreward]", $"‖color:gui.orange‖{rewardText}‖end‖"),
|
||||
("[itemcount]", itemsToSpawn.Count.ToString()),
|
||||
("[maxitemcount]", maxItemCount.ToString()));
|
||||
}
|
||||
|
||||
return RichString.Rich(retVal);
|
||||
}
|
||||
public override void ClientReadInitial(IReadMessage msg)
|
||||
{
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Barotrauma
|
||||
{
|
||||
partial class CombatMission : Mission
|
||||
{
|
||||
public override string Description
|
||||
public override LocalizedString Description
|
||||
{
|
||||
get
|
||||
{
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace Barotrauma
|
||||
|
||||
for(int i = 0; i < resourceClusters.Count; i++)
|
||||
{
|
||||
var identifier = msg.ReadString();
|
||||
var identifier = msg.ReadIdentifier();
|
||||
var count = msg.ReadByte();
|
||||
var resources = new Item[count];
|
||||
for (int j = 0; j < count; j++)
|
||||
|
||||
@@ -9,11 +9,8 @@ namespace Barotrauma
|
||||
{
|
||||
abstract partial class Mission
|
||||
{
|
||||
private readonly List<string> shownMessages = new List<string>();
|
||||
public IEnumerable<string> ShownMessages
|
||||
{
|
||||
get { return shownMessages; }
|
||||
}
|
||||
private readonly List<LocalizedString> shownMessages = new List<LocalizedString>();
|
||||
public IEnumerable<LocalizedString> ShownMessages => shownMessages;
|
||||
|
||||
public bool DisplayTargetHudIcons => Prefab.DisplayTargetHudIcons;
|
||||
|
||||
@@ -32,29 +29,29 @@ namespace Barotrauma
|
||||
{
|
||||
int v = Difficulty ?? MissionPrefab.MinDifficulty;
|
||||
float t = MathUtils.InverseLerp(MissionPrefab.MinDifficulty, MissionPrefab.MaxDifficulty, v);
|
||||
return ToolBox.GradientLerp(t, GUI.Style.Green, GUI.Style.Orange, GUI.Style.Red);
|
||||
return ToolBox.GradientLerp(t, GUIStyle.Green, GUIStyle.Orange, GUIStyle.Red);
|
||||
}
|
||||
|
||||
public virtual string GetMissionRewardText(Submarine sub)
|
||||
public virtual RichString GetMissionRewardText(Submarine sub)
|
||||
{
|
||||
string rewardText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", GetReward(sub)));
|
||||
return TextManager.GetWithVariable("missionreward", "[reward]", $"‖color:gui.orange‖{rewardText}‖end‖");
|
||||
LocalizedString rewardText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", GetReward(sub)));
|
||||
return RichString.Rich(TextManager.GetWithVariable("missionreward", "[reward]", "‖color:gui.orange‖"+rewardText+"‖end‖"));
|
||||
}
|
||||
|
||||
public string GetReputationRewardText(Location currLocation)
|
||||
public RichString GetReputationRewardText(Location currLocation)
|
||||
{
|
||||
List<string> reputationRewardTexts = new List<string>();
|
||||
List<LocalizedString> reputationRewardTexts = new List<LocalizedString>();
|
||||
foreach (var reputationReward in ReputationRewards)
|
||||
{
|
||||
string name = "";
|
||||
LocalizedString name = "";
|
||||
|
||||
if (reputationReward.Key.Equals("location", StringComparison.OrdinalIgnoreCase))
|
||||
if (reputationReward.Key == "location")
|
||||
{
|
||||
name = $"‖color:gui.orange‖{currLocation.Name}‖end‖";
|
||||
}
|
||||
else
|
||||
{
|
||||
var faction = FactionPrefab.Prefabs.Find(f => f.Identifier.Equals(reputationReward.Key, StringComparison.OrdinalIgnoreCase));
|
||||
var faction = FactionPrefab.Prefabs.Find(f => f.Identifier == reputationReward.Key);
|
||||
if (faction != null)
|
||||
{
|
||||
name = $"‖color:{XMLExtensions.ColorToString(faction.IconColor)}‖{faction.Name}‖end‖";
|
||||
@@ -66,28 +63,28 @@ namespace Barotrauma
|
||||
}
|
||||
float normalizedValue = MathUtils.InverseLerp(-100.0f, 100.0f, reputationReward.Value);
|
||||
string formattedValue = ((int)reputationReward.Value).ToString("+#;-#;0"); //force plus sign for positive numbers
|
||||
string rewardText = TextManager.GetWithVariables(
|
||||
LocalizedString rewardText = TextManager.GetWithVariables(
|
||||
"reputationformat",
|
||||
new string[] { "[reputationname]", "[reputationvalue]" },
|
||||
new string[] { name, $"‖color:{XMLExtensions.ColorToString(Reputation.GetReputationColor(normalizedValue))}‖{formattedValue}‖end‖" });
|
||||
reputationRewardTexts.Add(rewardText);
|
||||
("[reputationname]", name),
|
||||
("[reputationvalue]", $"‖color:{XMLExtensions.ColorToString(Reputation.GetReputationColor(normalizedValue))}‖{formattedValue}‖end‖" ));
|
||||
reputationRewardTexts.Add(rewardText.Value);
|
||||
}
|
||||
return TextManager.AddPunctuation(':', TextManager.Get("reputation"), string.Join(", ", reputationRewardTexts));
|
||||
return RichString.Rich(TextManager.AddPunctuation(':', TextManager.Get("reputation"), LocalizedString.Join(", ", reputationRewardTexts)));
|
||||
}
|
||||
|
||||
partial void ShowMessageProjSpecific(int missionState)
|
||||
{
|
||||
int messageIndex = missionState - 1;
|
||||
if (messageIndex >= Headers.Count && messageIndex >= Messages.Count) { return; }
|
||||
if (messageIndex >= Headers.Length && messageIndex >= Messages.Length) { return; }
|
||||
if (messageIndex < 0) { return; }
|
||||
|
||||
string header = messageIndex < Headers.Count ? Headers[messageIndex] : "";
|
||||
string message = messageIndex < Messages.Count ? Messages[messageIndex] : "";
|
||||
LocalizedString header = messageIndex < Headers.Length ? Headers[messageIndex] : "";
|
||||
LocalizedString message = messageIndex < Messages.Length ? Messages[messageIndex] : "";
|
||||
|
||||
CoroutineManager.StartCoroutine(ShowMessageBoxAfterRoundSummary(header, message));
|
||||
}
|
||||
|
||||
private IEnumerable<CoroutineStatus> ShowMessageBoxAfterRoundSummary(string header, string message)
|
||||
private IEnumerable<CoroutineStatus> ShowMessageBoxAfterRoundSummary(LocalizedString header, LocalizedString message)
|
||||
{
|
||||
while (GUIMessageBox.VisibleBox?.UserData is RoundSummary)
|
||||
{
|
||||
@@ -97,10 +94,10 @@ namespace Barotrauma
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
protected void CreateMessageBox(string header, string message)
|
||||
protected void CreateMessageBox(LocalizedString header, LocalizedString message)
|
||||
{
|
||||
shownMessages.Add(message);
|
||||
new GUIMessageBox(header, message, buttons: new string[0], type: GUIMessageBox.Type.InGame, icon: Prefab.Icon, parseRichText: true)
|
||||
new GUIMessageBox(RichString.Rich(header), RichString.Rich(message), buttons: Array.Empty<LocalizedString>(), type: GUIMessageBox.Type.InGame, icon: Prefab.Icon)
|
||||
{
|
||||
IconColor = Prefab.IconColor
|
||||
};
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace Barotrauma
|
||||
using System;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
abstract partial class MissionMode : GameMode
|
||||
{
|
||||
@@ -6,7 +8,7 @@
|
||||
{
|
||||
foreach (Mission mission in missions)
|
||||
{
|
||||
new GUIMessageBox(mission.Name, mission.Description, new string[0], type: GUIMessageBox.Type.InGame, icon: mission.Prefab.Icon, parseRichText: true)
|
||||
new GUIMessageBox(RichString.Rich(mission.Name), RichString.Rich(mission.Description), Array.Empty<LocalizedString>(), type: GUIMessageBox.Type.InGame, icon: mission.Prefab.Icon)
|
||||
{
|
||||
IconColor = mission.Prefab.IconColor,
|
||||
UserData = "missionstartmessage"
|
||||
|
||||
@@ -4,7 +4,7 @@ using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class MissionPrefab
|
||||
partial class MissionPrefab : PrefabWithUintIdentifier
|
||||
{
|
||||
public Sprite Icon
|
||||
{
|
||||
@@ -49,11 +49,11 @@ namespace Barotrauma
|
||||
private Sprite hudIcon;
|
||||
private Color? hudIconColor;
|
||||
|
||||
partial void InitProjSpecific(XElement element)
|
||||
partial void InitProjSpecific(ContentXElement element)
|
||||
{
|
||||
DisplayTargetHudIcons = element.GetAttributeBool("displaytargethudicons", false);
|
||||
HudIconMaxDistance = element.GetAttributeFloat("hudiconmaxdistance", 1000.0f);
|
||||
foreach (XElement subElement in element.Elements())
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
string name = subElement.Name.ToString();
|
||||
if (name.Equals("icon", StringComparison.OrdinalIgnoreCase))
|
||||
@@ -68,5 +68,10 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
partial void DisposeProjectSpecific()
|
||||
{
|
||||
Icon?.Remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using Microsoft.Xna.Framework.Graphics;
|
||||
using SharpFont;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
@@ -19,7 +20,6 @@ namespace Barotrauma
|
||||
private Face face;
|
||||
private uint size;
|
||||
private int baseHeight;
|
||||
//private int lineHeight;
|
||||
private Dictionary<uint, GlyphData> texCoords;
|
||||
private List<Texture2D> textures;
|
||||
private GraphicsDevice graphicsDevice;
|
||||
@@ -53,6 +53,8 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public bool ForceUpperCase = false;
|
||||
|
||||
public float LineHeight => baseHeight * 1.8f;
|
||||
|
||||
private uint[] charRanges;
|
||||
@@ -79,9 +81,9 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public ScalableFont(XElement element, GraphicsDevice gd = null)
|
||||
public ScalableFont(ContentXElement element, GraphicsDevice gd = null)
|
||||
: this(
|
||||
element.GetAttributeString("file", ""),
|
||||
element.GetAttributeContentPath("file")?.Value,
|
||||
(uint)element.GetAttributeInt("size", 14),
|
||||
gd,
|
||||
element.GetAttributeBool("dynamicloading", false),
|
||||
@@ -104,10 +106,7 @@ namespace Barotrauma
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (this.face == null)
|
||||
{
|
||||
this.face = new Face(Lib, filename);
|
||||
}
|
||||
this.face ??= new Face(Lib, filename);
|
||||
this.size = size;
|
||||
this.textures = new List<Texture2D>();
|
||||
this.texCoords = new Dictionary<uint, GlyphData>();
|
||||
@@ -186,7 +185,7 @@ namespace Barotrauma
|
||||
GlyphData blankData = new GlyphData(
|
||||
advance: (float)face.Glyph.Metrics.HorizontalAdvance,
|
||||
texIndex: -1); //indicates no texture because the glyph is empty
|
||||
|
||||
|
||||
texCoords.Add(j, blankData);
|
||||
}
|
||||
continue;
|
||||
@@ -399,6 +398,52 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: refactor this further
|
||||
private void HandleNewLineAndAlignment(
|
||||
string text,
|
||||
in Vector2 advanceUnit,
|
||||
in Vector2 position,
|
||||
in Vector2 scale,
|
||||
Alignment alignment,
|
||||
int i,
|
||||
ref float lineWidth,
|
||||
ref Vector2 currentLineOffset,
|
||||
ref int lineNum,
|
||||
ref Vector2 currentPos,
|
||||
out uint charIndex,
|
||||
out bool shouldContinue)
|
||||
{
|
||||
if ((alignment.HasFlag(Alignment.CenterX) || alignment.HasFlag(Alignment.Right)) && (lineWidth < 0.0f || text[i] == '\n'))
|
||||
{
|
||||
int startIndex = lineWidth < 0.0f ? i : (i + 1);
|
||||
lineWidth = 0.0f;
|
||||
for (int j = startIndex; j < text.Length; j++)
|
||||
{
|
||||
if (text[j] == '\n') { break; }
|
||||
uint chrIndex = text[j];
|
||||
|
||||
var gd2 = GetGlyphData(chrIndex);
|
||||
lineWidth += gd2.Advance;
|
||||
}
|
||||
currentLineOffset = -lineWidth * advanceUnit * scale.X;
|
||||
if (alignment.HasFlag(Alignment.CenterX)) { currentLineOffset *= 0.5f; }
|
||||
|
||||
currentLineOffset.X = MathF.Round(currentLineOffset.X);
|
||||
currentLineOffset.Y = MathF.Round(currentLineOffset.Y);
|
||||
}
|
||||
if (text[i] == '\n')
|
||||
{
|
||||
lineNum++;
|
||||
currentPos = position;
|
||||
currentPos.X -= LineHeight * lineNum * advanceUnit.Y * scale.Y;
|
||||
currentPos.Y += LineHeight * lineNum * advanceUnit.X * scale.Y;
|
||||
shouldContinue = true; charIndex = 0; return;
|
||||
}
|
||||
|
||||
shouldContinue = false;
|
||||
charIndex = text[i];
|
||||
}
|
||||
|
||||
private GlyphData GetGlyphData(uint charIndex)
|
||||
{
|
||||
const uint DEFAULT_INDEX = 0x25A1; //U+25A1 = white square
|
||||
@@ -412,29 +457,27 @@ namespace Barotrauma
|
||||
return new GlyphData(texIndex: -1);
|
||||
}
|
||||
|
||||
public void DrawString(SpriteBatch sb, string text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects se, float layerDepth)
|
||||
public void DrawString(SpriteBatch sb, string text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects se, float layerDepth, Alignment alignment = Alignment.TopLeft, ForceUpperCase forceUpperCase = Barotrauma.ForceUpperCase.Inherit)
|
||||
{
|
||||
if (textures.Count == 0 && !DynamicLoading) { return; }
|
||||
text = ApplyUpperCase(text, forceUpperCase);
|
||||
if (DynamicLoading)
|
||||
{
|
||||
DynamicRenderAtlas(graphicsDevice, text);
|
||||
}
|
||||
|
||||
float lineWidth = -1.0f;
|
||||
Vector2 currentLineOffset = Vector2.Zero;
|
||||
|
||||
int lineNum = 0;
|
||||
Vector2 currentPos = position;
|
||||
Vector2 advanceUnit = rotation == 0.0f ? Vector2.UnitX : new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation));
|
||||
for (int i = 0; i < text.Length; i++)
|
||||
{
|
||||
if (text[i] == '\n')
|
||||
{
|
||||
lineNum++;
|
||||
currentPos = position;
|
||||
currentPos.X -= LineHeight * lineNum * advanceUnit.Y * scale.Y;
|
||||
currentPos.Y += LineHeight * lineNum * advanceUnit.X * scale.Y;
|
||||
continue;
|
||||
}
|
||||
|
||||
uint charIndex = text[i];
|
||||
HandleNewLineAndAlignment(text, advanceUnit, position, scale, alignment, i,
|
||||
ref lineWidth, ref currentLineOffset, ref lineNum, ref currentPos,
|
||||
out uint charIndex, out bool shouldContinue);
|
||||
if (shouldContinue) { continue; }
|
||||
|
||||
GlyphData gd = GetGlyphData(charIndex);
|
||||
if (gd.TexIndex >= 0)
|
||||
@@ -444,20 +487,30 @@ namespace Barotrauma
|
||||
drawOffset.X = gd.DrawOffset.X * advanceUnit.X * scale.X - gd.DrawOffset.Y * advanceUnit.Y * scale.Y;
|
||||
drawOffset.Y = gd.DrawOffset.X * advanceUnit.Y * scale.Y + gd.DrawOffset.Y * advanceUnit.X * scale.X;
|
||||
|
||||
sb.Draw(tex, currentPos + drawOffset, gd.TexCoords, color, rotation, origin, scale, se, layerDepth);
|
||||
sb.Draw(tex, currentPos + currentLineOffset + drawOffset, gd.TexCoords, color, rotation, origin, scale, se, layerDepth);
|
||||
}
|
||||
currentPos += gd.Advance * advanceUnit * scale.X;
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawString(SpriteBatch sb, string text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects se, float layerDepth)
|
||||
public void DrawString(SpriteBatch sb, string text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects se, float layerDepth, Alignment alignment = Alignment.TopLeft, ForceUpperCase forceUpperCase = Barotrauma.ForceUpperCase.Inherit)
|
||||
{
|
||||
DrawString(sb, text, position, color, rotation, origin, new Vector2(scale), se, layerDepth);
|
||||
DrawString(sb, text, position, color, rotation, origin, new Vector2(scale), se, layerDepth, alignment, forceUpperCase);
|
||||
}
|
||||
|
||||
public void DrawString(SpriteBatch sb, string text, Vector2 position, Color color)
|
||||
private string ApplyUpperCase(string text, ForceUpperCase forceUpperCase)
|
||||
=> forceUpperCase switch
|
||||
{
|
||||
Barotrauma.ForceUpperCase.Inherit => ForceUpperCase ? text.ToUpper() : text,
|
||||
Barotrauma.ForceUpperCase.Yes => text.ToUpper(),
|
||||
Barotrauma.ForceUpperCase.No => text
|
||||
};
|
||||
|
||||
private readonly static VertexPositionColorTexture[] quadVertices = new VertexPositionColorTexture[4];
|
||||
public void DrawString(SpriteBatch sb, string text, Vector2 position, Color color, ForceUpperCase forceUpperCase = Barotrauma.ForceUpperCase.Inherit, bool italics = false)
|
||||
{
|
||||
if (textures.Count == 0 && !DynamicLoading) { return; }
|
||||
text = ApplyUpperCase(text, forceUpperCase);
|
||||
if (DynamicLoading)
|
||||
{
|
||||
DynamicRenderAtlas(graphicsDevice, text);
|
||||
@@ -478,21 +531,48 @@ namespace Barotrauma
|
||||
GlyphData gd = GetGlyphData(charIndex);
|
||||
if (gd.TexIndex >= 0)
|
||||
{
|
||||
float halfCharHeight = gd.TexCoords.Height * 0.5f;
|
||||
float slantStrength = 0.35f;
|
||||
float topItalicOffset = italics ? ((halfCharHeight - gd.DrawOffset.Y) * slantStrength) + baseHeight * 0.18f : 0.0f;
|
||||
float bottomItalicOffset = italics ? ((-halfCharHeight - gd.DrawOffset.Y) * slantStrength) + baseHeight * 0.18f : 0.0f;
|
||||
|
||||
Texture2D tex = textures[gd.TexIndex];
|
||||
sb.Draw(tex, currentPos + gd.DrawOffset, gd.TexCoords, color);
|
||||
quadVertices[0].Position = new Vector3(currentPos + gd.DrawOffset + (bottomItalicOffset, gd.TexCoords.Height), 0.0f);
|
||||
quadVertices[0].TextureCoordinate = ((float)gd.TexCoords.Left / tex.Width, (float)gd.TexCoords.Bottom / tex.Height);
|
||||
quadVertices[0].Color = color;
|
||||
|
||||
quadVertices[1].Position = new Vector3(currentPos + gd.DrawOffset + (topItalicOffset, 0.0f), 0.0f);
|
||||
quadVertices[1].TextureCoordinate = ((float)gd.TexCoords.Left / tex.Width, (float)gd.TexCoords.Top / tex.Height);
|
||||
quadVertices[1].Color = color;
|
||||
|
||||
quadVertices[2].Position = new Vector3(currentPos + gd.DrawOffset + (gd.TexCoords.Width + bottomItalicOffset, gd.TexCoords.Height), 0.0f);
|
||||
quadVertices[2].TextureCoordinate = ((float)gd.TexCoords.Right / tex.Width, (float)gd.TexCoords.Bottom / tex.Height);
|
||||
quadVertices[2].Color = color;
|
||||
|
||||
quadVertices[3].Position = new Vector3(currentPos + gd.DrawOffset + (gd.TexCoords.Width + topItalicOffset, 0.0f), 0.0f);
|
||||
quadVertices[3].TextureCoordinate = ((float)gd.TexCoords.Right / tex.Width, (float)gd.TexCoords.Top / tex.Height);
|
||||
quadVertices[3].Color = color;
|
||||
|
||||
sb.Draw(tex, quadVertices, 0.0f);
|
||||
}
|
||||
currentPos.X += gd.Advance;
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawStringWithColors(SpriteBatch sb, string text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects se, float layerDepth, List<RichTextData> richTextData, int rtdOffset = 0)
|
||||
public void DrawStringWithColors(SpriteBatch sb, string text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects se, float layerDepth, in ImmutableArray<RichTextData>? richTextData, int rtdOffset = 0, Alignment alignment = Alignment.TopLeft, ForceUpperCase forceUpperCase = Barotrauma.ForceUpperCase.Inherit)
|
||||
{
|
||||
DrawStringWithColors(sb, text, position, color, rotation, origin, new Vector2(scale), se, layerDepth, richTextData, rtdOffset);
|
||||
DrawStringWithColors(sb, text, position, color, rotation, origin, new Vector2(scale), se, layerDepth, richTextData, rtdOffset, alignment, forceUpperCase);
|
||||
}
|
||||
|
||||
public void DrawStringWithColors(SpriteBatch sb, string text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects se, float layerDepth, List<RichTextData> richTextData, int rtdOffset = 0)
|
||||
public void DrawStringWithColors(SpriteBatch sb, string text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects se, float layerDepth, in ImmutableArray<RichTextData>? richTextData, int rtdOffset = 0, Alignment alignment = Alignment.TopLeft, ForceUpperCase forceUpperCase = Barotrauma.ForceUpperCase.Inherit)
|
||||
{
|
||||
if (textures.Count == 0 && !DynamicLoading) { return; }
|
||||
if (!richTextData.HasValue || richTextData.Value.Length <= 0) { DrawString(sb, text, position, color, rotation, origin, scale, se, layerDepth, forceUpperCase: forceUpperCase); return; }
|
||||
|
||||
text = ApplyUpperCase(text, forceUpperCase);
|
||||
|
||||
float lineWidth = -1.0f;
|
||||
Vector2 currentLineOffset = Vector2.Zero;
|
||||
if (DynamicLoading)
|
||||
{
|
||||
DynamicRenderAtlas(graphicsDevice, text);
|
||||
@@ -503,27 +583,21 @@ namespace Barotrauma
|
||||
Vector2 advanceUnit = rotation == 0.0f ? Vector2.UnitX : new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation));
|
||||
|
||||
int richTextDataIndex = 0;
|
||||
RichTextData currentRichTextData = richTextData[richTextDataIndex];
|
||||
RichTextData currentRichTextData = richTextData.Value[richTextDataIndex];
|
||||
|
||||
for (int i = 0; i < text.Length; i++)
|
||||
{
|
||||
if (text[i] == '\n')
|
||||
{
|
||||
lineNum++;
|
||||
currentPos = position;
|
||||
currentPos.X -= LineHeight * lineNum * advanceUnit.Y * scale.Y;
|
||||
currentPos.Y += LineHeight * lineNum * advanceUnit.X * scale.Y;
|
||||
continue;
|
||||
}
|
||||
|
||||
uint charIndex = text[i];
|
||||
HandleNewLineAndAlignment(text, advanceUnit, position, scale, alignment, i,
|
||||
ref lineWidth, ref currentLineOffset, ref lineNum, ref currentPos,
|
||||
out uint charIndex, out bool shouldContinue);
|
||||
if (shouldContinue) { continue; }
|
||||
|
||||
Color currentTextColor;
|
||||
|
||||
while (currentRichTextData != null && i + rtdOffset > currentRichTextData.EndIndex + lineNum)
|
||||
{
|
||||
richTextDataIndex++;
|
||||
currentRichTextData = richTextDataIndex < richTextData.Count ? richTextData[richTextDataIndex] : null;
|
||||
currentRichTextData = richTextDataIndex < richTextData.Value.Length ? richTextData.Value[richTextDataIndex] : null;
|
||||
}
|
||||
|
||||
if (currentRichTextData != null && currentRichTextData.StartIndex + lineNum <= i + rtdOffset && i + rtdOffset <= currentRichTextData.EndIndex + lineNum)
|
||||
@@ -547,7 +621,7 @@ namespace Barotrauma
|
||||
drawOffset.X = gd.DrawOffset.X * advanceUnit.X * scale.X - gd.DrawOffset.Y * advanceUnit.Y * scale.Y;
|
||||
drawOffset.Y = gd.DrawOffset.X * advanceUnit.Y * scale.Y + gd.DrawOffset.Y * advanceUnit.X * scale.X;
|
||||
|
||||
sb.Draw(tex, currentPos + drawOffset, gd.TexCoords, currentTextColor, rotation, origin, scale, se, layerDepth);
|
||||
sb.Draw(tex, currentPos + currentLineOffset + drawOffset, gd.TexCoords, currentTextColor, rotation, origin, scale, se, layerDepth);
|
||||
}
|
||||
currentPos += gd.Advance * advanceUnit * scale.X;
|
||||
}
|
||||
@@ -628,6 +702,8 @@ namespace Barotrauma
|
||||
//A breaker (whitespace or CJK) was found earlier
|
||||
//in this line, so let's break the line there
|
||||
i = lastBreakerIndex.Value + 1;
|
||||
gd = GetGlyphData(text[i]);
|
||||
advance = gd.Advance;
|
||||
}
|
||||
|
||||
nextLine();
|
||||
@@ -648,7 +724,12 @@ namespace Barotrauma
|
||||
requestedCharPos = foundCharPos;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public Vector2 MeasureString(LocalizedString str, bool removeExtraSpacing = false)
|
||||
{
|
||||
return MeasureString(str.Value, removeExtraSpacing);
|
||||
}
|
||||
|
||||
public Vector2 MeasureString(string text, bool removeExtraSpacing = false)
|
||||
{
|
||||
if (text == null)
|
||||
|
||||
@@ -25,12 +25,14 @@ namespace Barotrauma
|
||||
get { return _toggleOpen; }
|
||||
set
|
||||
{
|
||||
_toggleOpen = GameMain.Config.ChatOpen = value;
|
||||
if (value) hideableElements.Visible = true;
|
||||
_toggleOpen = PreferChatBoxOpen = value;
|
||||
if (value) { hideableElements.Visible = true; }
|
||||
}
|
||||
}
|
||||
private float openState;
|
||||
|
||||
public static bool PreferChatBoxOpen = true;
|
||||
|
||||
public bool CloseAfterMessageSent;
|
||||
|
||||
private float prevUIScale;
|
||||
@@ -99,6 +101,7 @@ namespace Barotrauma
|
||||
var channelSettingsContent = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), channelSettingsFrame.RectTransform, Anchor.Center), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||
{
|
||||
Stretch = true,
|
||||
CanBeFocused = true,
|
||||
RelativeSpacing = 0.01f
|
||||
};
|
||||
|
||||
@@ -119,9 +122,9 @@ namespace Barotrauma
|
||||
Color = new Color(51, 59, 46),
|
||||
SpriteEffects = Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally
|
||||
};
|
||||
arrowIcon.HoverColor = arrowIcon.PressedColor = arrowIcon.PressedColor = arrowIcon.Color;
|
||||
arrowIcon.HoverColor = arrowIcon.PressedColor = arrowIcon.SelectedColor = arrowIcon.Color;
|
||||
|
||||
channelText = new GUITextBox(new RectTransform(new Vector2(0.25f, 0.8f), channelSettingsContent.RectTransform), style: "DigitalFrameLight", textAlignment: Alignment.Center, font: GUI.DigitalFont)
|
||||
channelText = new GUITextBox(new RectTransform(new Vector2(0.25f, 0.8f), channelSettingsContent.RectTransform), style: "DigitalFrameLight", textAlignment: Alignment.Center, font: GUIStyle.DigitalFont)
|
||||
{
|
||||
textFilterFunction = text =>
|
||||
{
|
||||
@@ -173,7 +176,7 @@ namespace Barotrauma
|
||||
new GUIButton(new RectTransform(new Vector2(0.1f, 1.0f), channelPickerContent.RectTransform), i.ToString(), style: "GUITextBlock")
|
||||
{
|
||||
TextColor = new Color(51, 59, 46),
|
||||
SelectedTextColor = GUI.Style.Green,
|
||||
SelectedTextColor = GUIStyle.Green,
|
||||
UserData = i,
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
@@ -185,13 +188,13 @@ namespace Barotrauma
|
||||
int.TryParse(channelText.Text, out int newChannel);
|
||||
radio.SetChannelMemory(index, newChannel);
|
||||
btn.ToolTip = TextManager.GetWithVariables("radiochannelpreset",
|
||||
new string[] { "[index]", "[channel]" },
|
||||
new string[] { index.ToString(), radio.GetChannelMemory(index).ToString() });
|
||||
("[index]", index.ToString()),
|
||||
("[channel]", radio.GetChannelMemory(index).ToString()));
|
||||
channelMemPending = false;
|
||||
channelPickerContent.Children.First().CanBeFocused = true;
|
||||
memButton.Enabled = true;
|
||||
channelPickerContent.Flash(GUI.Style.Green);
|
||||
channelText.Flash(GUI.Style.Green);
|
||||
channelPickerContent.Flash(GUIStyle.Green);
|
||||
channelText.Flash(GUIStyle.Green);
|
||||
}
|
||||
SetChannel(radio.GetChannelMemory(index), setText: true);
|
||||
SoundPlayer.PlayUISound(GUISoundType.PopupMenu);
|
||||
@@ -224,7 +227,7 @@ namespace Barotrauma
|
||||
style: "ChatTextBox")
|
||||
{
|
||||
OverflowClip = true,
|
||||
Font = GUI.SmallFont,
|
||||
Font = GUIStyle.SmallFont,
|
||||
MaxTextLength = ChatMessage.MaxLength
|
||||
};
|
||||
|
||||
@@ -265,7 +268,7 @@ namespace Barotrauma
|
||||
};
|
||||
|
||||
showNewMessagesButton.Visible = false;
|
||||
ToggleOpen = GameMain.Config.ChatOpen;
|
||||
ToggleOpen = PreferChatBoxOpen = GameSettings.CurrentConfig.ChatOpen;
|
||||
}
|
||||
|
||||
public bool TypingChatMessage(GUITextBox textBox, string text)
|
||||
@@ -337,7 +340,7 @@ namespace Barotrauma
|
||||
color: ((chatBox.Content.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f);
|
||||
|
||||
GUITextBlock senderNameTimestamp = new GUITextBlock(new RectTransform(new Vector2(0.98f, 0.0f), msgHolder.RectTransform) { AbsoluteOffset = new Point((int)(5 * GUI.Scale), 0) },
|
||||
ChatMessage.GetTimeStamp(), textColor: Color.LightGray, font: GUI.SmallFont, textAlignment: Alignment.TopLeft, style: null)
|
||||
ChatMessage.GetTimeStamp(), textColor: Color.LightGray, font: GUIStyle.SmallFont, textAlignment: Alignment.TopLeft, style: null)
|
||||
{
|
||||
CanBeFocused = true
|
||||
};
|
||||
@@ -350,9 +353,9 @@ namespace Barotrauma
|
||||
{
|
||||
Padding = Vector4.Zero
|
||||
},
|
||||
Font = GUI.SmallFont,
|
||||
Font = GUIStyle.SmallFont,
|
||||
CanBeFocused = true,
|
||||
ForceUpperCase = false,
|
||||
ForceUpperCase = ForceUpperCase.No,
|
||||
UserData = message.SenderClient,
|
||||
OnClicked = (_, o) =>
|
||||
{
|
||||
@@ -379,8 +382,8 @@ namespace Barotrauma
|
||||
|
||||
var msgText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), msgHolder.RectTransform)
|
||||
{ AbsoluteOffset = new Point((int)(10 * GUI.Scale), senderNameTimestamp == null ? 0 : senderNameTimestamp.Rect.Height) },
|
||||
displayedText, textColor: message.Color, font: GUI.SmallFont, textAlignment: Alignment.TopLeft, style: null, wrap: true,
|
||||
color: ((chatBox.Content.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f, parseRichText: true)
|
||||
RichString.Rich(displayedText), textColor: message.Color, font: GUIStyle.SmallFont, textAlignment: Alignment.TopLeft, style: null, wrap: true,
|
||||
color: ((chatBox.Content.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f)
|
||||
{
|
||||
UserData = message.SenderName,
|
||||
CanBeFocused = false
|
||||
@@ -454,7 +457,7 @@ namespace Barotrauma
|
||||
if (!string.IsNullOrEmpty(senderName))
|
||||
{
|
||||
var senderText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform),
|
||||
senderName, textColor: senderColor, style: null, font: GUI.SmallFont)
|
||||
senderName, textColor: senderColor, style: null, font: GUIStyle.SmallFont)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
@@ -462,7 +465,7 @@ namespace Barotrauma
|
||||
senderText.RectTransform.MinSize = new Point(0, senderText.Rect.Height);
|
||||
}
|
||||
var msgPopupText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform),
|
||||
displayedText, textColor: message.Color, font: GUI.SmallFont, textAlignment: Alignment.BottomLeft, style: null, wrap: true, parseRichText: true)
|
||||
RichString.Rich(displayedText), textColor: message.Color, font: GUIStyle.SmallFont, textAlignment: Alignment.BottomLeft, style: null, wrap: true)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
@@ -553,8 +556,8 @@ namespace Barotrauma
|
||||
{
|
||||
int index = (int)presetButton.UserData;
|
||||
presetButton.ToolTip = TextManager.GetWithVariables("radiochannelpreset",
|
||||
new string[] { "[index]", "[channel]" },
|
||||
new string[] { index.ToString(), radio.GetChannelMemory(index).ToString() });
|
||||
("[index]", index.ToString()),
|
||||
("[channel]", radio.GetChannelMemory(index).ToString()));
|
||||
}
|
||||
SetChannel(radio.Channel, setText: true);
|
||||
prevRadio = radio;
|
||||
@@ -563,7 +566,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (channelPickerContent.FlashTimer <= 0)
|
||||
{
|
||||
channelPickerContent.Flash(GUI.Style.Green, flashRectInflate: new Vector2(GUI.Scale * 5.0f));
|
||||
channelPickerContent.Flash(GUIStyle.Green, flashRectInflate: new Vector2(GUI.Scale * 5.0f));
|
||||
}
|
||||
if (PlayerInput.PrimaryMouseButtonClicked() && !GUI.IsMouseOn(channelPickerContent))
|
||||
{
|
||||
@@ -671,7 +674,7 @@ namespace Barotrauma
|
||||
if (Character.Controlled != null && ChatMessage.CanUseRadio(Character.Controlled, out WifiComponent radio))
|
||||
{
|
||||
radio.Channel = channel;
|
||||
GameMain.Client?.CreateEntityEvent(radio.Item, new object[] { NetEntityEvent.Type.ChangeProperty, radio.SerializableProperties["channel"] });
|
||||
GameMain.Client?.CreateEntityEvent(radio.Item, new Item.ChangePropertyEventData(radio.SerializableProperties["channel".ToIdentifier()]));
|
||||
|
||||
if (setText)
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -16,7 +17,7 @@ namespace Barotrauma
|
||||
Toggle
|
||||
}
|
||||
|
||||
public class GUIComponentStyle
|
||||
public class GUIComponentStyle : GUIPrefab
|
||||
{
|
||||
public readonly Vector4 Padding;
|
||||
|
||||
@@ -35,31 +36,53 @@ namespace Barotrauma
|
||||
public readonly float ColorCrossFadeTime;
|
||||
public readonly TransitionMode TransitionMode;
|
||||
|
||||
public readonly string Font;
|
||||
public readonly Identifier Font;
|
||||
public readonly bool ForceUpperCase;
|
||||
|
||||
public readonly Color OutlineColor;
|
||||
|
||||
public readonly XElement Element;
|
||||
public readonly ContentXElement Element;
|
||||
|
||||
public readonly Dictionary<GUIComponent.ComponentState, List<UISprite>> Sprites;
|
||||
|
||||
public SpriteFallBackState FallBackState;
|
||||
|
||||
public Dictionary<string, GUIComponentStyle> ChildStyles;
|
||||
|
||||
public readonly GUIStyle Style;
|
||||
public readonly GUIComponentStyle ParentStyle;
|
||||
public readonly Dictionary<Identifier, GUIComponentStyle> ChildStyles;
|
||||
|
||||
public static GUIComponentStyle FromHierarchy(IReadOnlyList<Identifier> hierarchy)
|
||||
{
|
||||
if (hierarchy is null || hierarchy.None()) { return null; }
|
||||
GUIStyle.ComponentStyles.TryGet(hierarchy[0], out GUIComponentStyle style);
|
||||
for (int i = 1; i < hierarchy.Count; i++)
|
||||
{
|
||||
if (style is null) { return null; }
|
||||
style.ChildStyles.TryGetValue(hierarchy[i], out style);
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
||||
public static Identifier[] ToHierarchy(GUIComponentStyle style)
|
||||
{
|
||||
List<Identifier> ids = new List<Identifier>();
|
||||
while (style != null)
|
||||
{
|
||||
ids.Insert(0, style.Identifier);
|
||||
style = style.ParentStyle;
|
||||
}
|
||||
|
||||
return ids.ToArray();
|
||||
}
|
||||
|
||||
public readonly string Name;
|
||||
|
||||
public int? Width { get; private set; }
|
||||
public int? Height { get; private set; }
|
||||
|
||||
public GUIComponentStyle(XElement element, GUIStyle style)
|
||||
public GUIComponentStyle(ContentXElement element, UIStyleFile file, GUIComponentStyle parent = null) : base(element, file)
|
||||
{
|
||||
Name = element.Name.LocalName;
|
||||
|
||||
Style = style;
|
||||
Element = element;
|
||||
|
||||
Sprites = new Dictionary<GUIComponent.ComponentState, List<UISprite>>();
|
||||
@@ -68,7 +91,8 @@ namespace Barotrauma
|
||||
Sprites[state] = new List<UISprite>();
|
||||
}
|
||||
|
||||
ChildStyles = new Dictionary<string, GUIComponentStyle>();
|
||||
ParentStyle = parent;
|
||||
ChildStyles = new Dictionary<Identifier, GUIComponentStyle>();
|
||||
|
||||
Padding = element.GetAttributeVector4("padding", Vector4.Zero);
|
||||
|
||||
@@ -95,10 +119,10 @@ namespace Barotrauma
|
||||
FallBackState = s;
|
||||
}
|
||||
|
||||
Font = element.GetAttributeString("font", "");
|
||||
Font = element.GetAttributeIdentifier("font", "");
|
||||
ForceUpperCase = element.GetAttributeBool("forceuppercase", false);
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
@@ -106,7 +130,7 @@ namespace Barotrauma
|
||||
UISprite newSprite = new UISprite(subElement);
|
||||
|
||||
GUIComponent.ComponentState spriteState = GUIComponent.ComponentState.None;
|
||||
if (subElement.Attribute("state") != null)
|
||||
if (subElement.GetAttribute("state") != null)
|
||||
{
|
||||
string stateStr = subElement.GetAttributeString("state", "None");
|
||||
Enum.TryParse(stateStr, out spriteState);
|
||||
@@ -128,15 +152,15 @@ namespace Barotrauma
|
||||
case "size":
|
||||
break;
|
||||
default:
|
||||
string styleName = subElement.Name.ToString().ToLowerInvariant();
|
||||
Identifier styleName = subElement.NameAsIdentifier();
|
||||
if (ChildStyles.ContainsKey(styleName))
|
||||
{
|
||||
DebugConsole.ThrowError("UI style \"" + element.Name.ToString() + "\" contains multiple child styles with the same name (\"" + styleName + "\")!");
|
||||
ChildStyles[styleName] = new GUIComponentStyle(subElement, style);
|
||||
ChildStyles[styleName] = new GUIComponentStyle(subElement, file, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
ChildStyles.Add(styleName, new GUIComponentStyle(subElement, style));
|
||||
ChildStyles.Add(styleName, new GUIComponentStyle(subElement, file, this));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -157,7 +181,7 @@ namespace Barotrauma
|
||||
public void GetSize(XElement element)
|
||||
{
|
||||
Point size = new Point(0, 0);
|
||||
foreach (XElement subElement in element.Elements())
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
if (!subElement.Name.ToString().Equals("size", StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||
Point maxResolution = subElement.GetAttributePoint("maxresolution", new Point(int.MaxValue, int.MaxValue));
|
||||
@@ -172,5 +196,7 @@ namespace Barotrauma
|
||||
if (size.X > 0) { Width = size.X; }
|
||||
if (size.Y > 0) { Height = size.Y; }
|
||||
}
|
||||
|
||||
public override void Dispose() { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Barotrauma
|
||||
private GUIButton clearAllButton;
|
||||
|
||||
private List<CharacterInfo> PendingHires => campaign.Map?.CurrentLocation?.HireManager?.PendingHires;
|
||||
private bool HasPermission => campaignUI.Campaign.AllowedToManageCampaign();
|
||||
private bool HasPermission => campaignUI.Campaign.AllowedToManageCampaign(ClientPermissions.ManageHires);
|
||||
|
||||
private Point resolutionWhenCreated;
|
||||
|
||||
@@ -108,10 +108,10 @@ namespace Barotrauma
|
||||
};
|
||||
var imageWidth = (float)headerGroup.Rect.Height / headerGroup.Rect.Width;
|
||||
new GUIImage(new RectTransform(new Vector2(imageWidth, 1.0f), headerGroup.RectTransform), "CrewManagementHeaderIcon");
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f - imageWidth, 1.0f), headerGroup.RectTransform), TextManager.Get("campaigncrew.header"), font: GUI.LargeFont)
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f - imageWidth, 1.0f), headerGroup.RectTransform), TextManager.Get("campaigncrew.header"), font: GUIStyle.LargeFont)
|
||||
{
|
||||
CanBeFocused = false,
|
||||
ForceUpperCase = true
|
||||
ForceUpperCase = ForceUpperCase.Yes
|
||||
};
|
||||
|
||||
var hireablesGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.95f), anchor: Anchor.Center,
|
||||
@@ -162,17 +162,17 @@ namespace Barotrauma
|
||||
RelativeSpacing = 0.005f
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), playerBalanceContainer.RectTransform),
|
||||
TextManager.Get("campaignstore.balance"), font: GUI.Font, textAlignment: Alignment.BottomRight)
|
||||
TextManager.Get("campaignstore.balance"), font: GUIStyle.Font, textAlignment: Alignment.BottomRight)
|
||||
{
|
||||
AutoScaleVertical = true,
|
||||
ForceUpperCase = true
|
||||
ForceUpperCase = ForceUpperCase.Yes
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), playerBalanceContainer.RectTransform),
|
||||
"", font: GUI.SubHeadingFont, textAlignment: Alignment.TopRight)
|
||||
"", font: GUIStyle.SubHeadingFont, textAlignment: Alignment.TopRight)
|
||||
{
|
||||
AutoScaleVertical = true,
|
||||
TextScale = 1.1f,
|
||||
TextGetter = () => FormatCurrency(campaign.Money)
|
||||
TextGetter = () => TextManager.FormatCurrency(campaign.Wallet.Balance)
|
||||
};
|
||||
|
||||
var pendingAndCrewGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.95f), anchor: Anchor.Center,
|
||||
@@ -182,13 +182,13 @@ namespace Barotrauma
|
||||
}).RectTransform));
|
||||
|
||||
float height = 0.05f;
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, height), pendingAndCrewGroup.RectTransform), TextManager.Get("campaigncrew.pending"), font: GUI.SubHeadingFont);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, height), pendingAndCrewGroup.RectTransform), TextManager.Get("campaigncrew.pending"), font: GUIStyle.SubHeadingFont);
|
||||
pendingList = new GUIListBox(new RectTransform(new Vector2(1.0f, 8 * height), pendingAndCrewGroup.RectTransform))
|
||||
{
|
||||
Spacing = 1
|
||||
};
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, height), pendingAndCrewGroup.RectTransform), TextManager.Get("campaignmenucrew"), font: GUI.SubHeadingFont);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, height), pendingAndCrewGroup.RectTransform), TextManager.Get("campaignmenucrew"), font: GUIStyle.SubHeadingFont);
|
||||
crewList = new GUIListBox(new RectTransform(new Vector2(1.0f, 8 * height), pendingAndCrewGroup.RectTransform))
|
||||
{
|
||||
Spacing = 1
|
||||
@@ -196,7 +196,7 @@ namespace Barotrauma
|
||||
|
||||
var group = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, height), pendingAndCrewGroup.RectTransform), isHorizontal: true);
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), group.RectTransform), TextManager.Get("campaignstore.total"));
|
||||
totalBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), group.RectTransform), "", font: GUI.SubHeadingFont, textAlignment: Alignment.Right)
|
||||
totalBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), group.RectTransform), "", font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Right)
|
||||
{
|
||||
TextScale = 1.1f
|
||||
};
|
||||
@@ -207,12 +207,12 @@ namespace Barotrauma
|
||||
validateHiresButton = new GUIButton(new RectTransform(new Vector2(1.0f / 3.0f, 1.0f), group.RectTransform), text: TextManager.Get("campaigncrew.validate"))
|
||||
{
|
||||
ClickSound = GUISoundType.HireRepairClick,
|
||||
ForceUpperCase = true,
|
||||
ForceUpperCase = ForceUpperCase.Yes,
|
||||
OnClicked = (b, o) => ValidateHires(PendingHires, true)
|
||||
};
|
||||
clearAllButton = new GUIButton(new RectTransform(new Vector2(1.0f / 3.0f, 1.0f), group.RectTransform), text: TextManager.Get("campaignstore.clearall"))
|
||||
{
|
||||
ForceUpperCase = true,
|
||||
ForceUpperCase = ForceUpperCase.Yes,
|
||||
Enabled = HasPermission,
|
||||
OnClicked = (b, o) => RemoveAllPendingHires()
|
||||
};
|
||||
@@ -302,30 +302,42 @@ namespace Barotrauma
|
||||
if (sortingMethod == SortingMethod.AlphabeticalAsc)
|
||||
{
|
||||
list.Content.RectTransform.SortChildren((x, y) =>
|
||||
(x.GUIComponent.UserData as Tuple<CharacterInfo, float>).Item1.Name.CompareTo((y.GUIComponent.UserData as Tuple<CharacterInfo, float>).Item1.Name));
|
||||
((InfoSkill)x.GUIComponent.UserData).CharacterInfo.Name.CompareTo(((InfoSkill)y.GUIComponent.UserData).CharacterInfo.Name));
|
||||
}
|
||||
else if (sortingMethod == SortingMethod.JobAsc)
|
||||
{
|
||||
SortCharacters(list, SortingMethod.AlphabeticalAsc);
|
||||
list.Content.RectTransform.SortChildren((x, y) =>
|
||||
String.Compare((x.GUIComponent.UserData as Tuple<CharacterInfo, float>)?.Item1.Job.Name, (y.GUIComponent.UserData as Tuple<CharacterInfo, float>).Item1.Job.Name, StringComparison.Ordinal));
|
||||
String.Compare(((InfoSkill)x.GUIComponent.UserData).CharacterInfo.Job.Name.Value, ((InfoSkill)y.GUIComponent.UserData).CharacterInfo.Job.Name.Value, StringComparison.Ordinal));
|
||||
}
|
||||
else if (sortingMethod == SortingMethod.PriceAsc || sortingMethod == SortingMethod.PriceDesc)
|
||||
{
|
||||
SortCharacters(list, SortingMethod.AlphabeticalAsc);
|
||||
list.Content.RectTransform.SortChildren((x, y) =>
|
||||
(x.GUIComponent.UserData as Tuple<CharacterInfo, float>).Item1.Salary.CompareTo((y.GUIComponent.UserData as Tuple<CharacterInfo, float>).Item1.Salary));
|
||||
((InfoSkill)x.GUIComponent.UserData).CharacterInfo.Salary.CompareTo(((InfoSkill)y.GUIComponent.UserData).CharacterInfo.Salary));
|
||||
if (sortingMethod == SortingMethod.PriceDesc) { list.Content.RectTransform.ReverseChildren(); }
|
||||
}
|
||||
else if (sortingMethod == SortingMethod.SkillAsc || sortingMethod == SortingMethod.SkillDesc)
|
||||
{
|
||||
SortCharacters(list, SortingMethod.AlphabeticalAsc);
|
||||
list.Content.RectTransform.SortChildren((x, y) =>
|
||||
(x.GUIComponent.UserData as Tuple<CharacterInfo, float>).Item2.CompareTo((y.GUIComponent.UserData as Tuple<CharacterInfo, float>).Item2));
|
||||
((InfoSkill)x.GUIComponent.UserData).SkillLevel.CompareTo(((InfoSkill)y.GUIComponent.UserData).SkillLevel));
|
||||
if (sortingMethod == SortingMethod.SkillDesc) { list.Content.RectTransform.ReverseChildren(); }
|
||||
}
|
||||
}
|
||||
|
||||
private readonly struct InfoSkill
|
||||
{
|
||||
public readonly CharacterInfo CharacterInfo;
|
||||
public readonly float SkillLevel;
|
||||
|
||||
public InfoSkill(CharacterInfo characterInfo, float skillLevel)
|
||||
{
|
||||
CharacterInfo = characterInfo;
|
||||
SkillLevel = skillLevel;
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateCharacterFrame(CharacterInfo characterInfo, GUIListBox listBox)
|
||||
{
|
||||
Skill skill = null;
|
||||
@@ -338,7 +350,7 @@ namespace Barotrauma
|
||||
|
||||
GUIFrame frame = new GUIFrame(new RectTransform(new Point(listBox.Content.Rect.Width, (int)(GUI.yScale * 55)), parent: listBox.Content.RectTransform), "ListBoxElement")
|
||||
{
|
||||
UserData = new Tuple<CharacterInfo, float>(characterInfo, skill?.Level ?? 0.0f)
|
||||
UserData = new InfoSkill(characterInfo, skill?.Level ?? 0.0f)
|
||||
};
|
||||
GUILayoutGroup mainGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), frame.RectTransform, anchor: Anchor.Center), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||
{
|
||||
@@ -363,7 +375,7 @@ namespace Barotrauma
|
||||
nameBlock.Text = ToolBox.LimitString(nameBlock.Text, nameBlock.Font, nameBlock.Rect.Width);
|
||||
|
||||
GUITextBlock jobBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), nameAndJobGroup.RectTransform),
|
||||
characterInfo.Job.Name, textColor: Color.White, font: GUI.SmallFont, textAlignment: Alignment.TopLeft)
|
||||
characterInfo.Job.Name, textColor: Color.White, font: GUIStyle.SmallFont, textAlignment: Alignment.TopLeft)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
@@ -374,7 +386,7 @@ namespace Barotrauma
|
||||
{
|
||||
GUILayoutGroup skillGroup = new GUILayoutGroup(new RectTransform(new Vector2(width, 0.6f), mainGroup.RectTransform), isHorizontal: true);
|
||||
float iconWidth = (float)skillGroup.Rect.Height / skillGroup.Rect.Width;
|
||||
GUIImage skillIcon = new GUIImage(new RectTransform(new Vector2(iconWidth, 1.0f), skillGroup.RectTransform), skill.Icon)
|
||||
GUIImage skillIcon = new GUIImage(new RectTransform(Vector2.One, skillGroup.RectTransform, scaleBasis: ScaleBasis.Smallest), skill.Icon, scaleToFit: true)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
@@ -388,7 +400,7 @@ namespace Barotrauma
|
||||
if (listBox != crewList)
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(width, 1.0f), mainGroup.RectTransform),
|
||||
FormatCurrency(characterInfo.Salary),
|
||||
TextManager.FormatCurrency(characterInfo.Salary),
|
||||
textAlignment: Alignment.Center)
|
||||
{
|
||||
CanBeFocused = false
|
||||
@@ -421,7 +433,7 @@ namespace Barotrauma
|
||||
else if (!btn.Enabled)
|
||||
{
|
||||
btn.ToolTip = string.Empty;
|
||||
btn.Enabled = true;
|
||||
btn.Enabled = HasPermission;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -448,7 +460,7 @@ namespace Barotrauma
|
||||
var confirmDialog = new GUIMessageBox(
|
||||
TextManager.Get("FireWarningHeader"),
|
||||
TextManager.GetWithVariable("FireWarningText", "[charactername]", ((CharacterInfo)obj).Name),
|
||||
new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||
new LocalizedString[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||
confirmDialog.Buttons[0].UserData = (CharacterInfo)obj;
|
||||
confirmDialog.Buttons[0].OnClicked = FireCharacter;
|
||||
confirmDialog.Buttons[0].OnClicked += confirmDialog.Close;
|
||||
@@ -510,10 +522,11 @@ namespace Barotrauma
|
||||
string name = listBox == hireableList ? characterInfo.OriginalName : characterInfo.Name;
|
||||
nameBlock.Text = ToolBox.LimitString(name, nameBlock.Font, nameBlock.Rect.Width);
|
||||
|
||||
if (characterInfo.HasGenders)
|
||||
if (characterInfo.HasSpecifierTags)
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoLabelGroup.RectTransform), TextManager.Get("gender"));
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoValueGroup.RectTransform), TextManager.Get(characterInfo.Gender.ToString()));
|
||||
var menuCategoryVar = characterInfo.Prefab.MenuCategoryVar;
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoLabelGroup.RectTransform), TextManager.Get(menuCategoryVar));
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoValueGroup.RectTransform), TextManager.Get(characterInfo.ReplaceVars($"[{menuCategoryVar}]")));
|
||||
}
|
||||
if (characterInfo.Job is Job job)
|
||||
{
|
||||
@@ -523,7 +536,7 @@ namespace Barotrauma
|
||||
if (characterInfo.PersonalityTrait is NPCPersonalityTrait trait)
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoLabelGroup.RectTransform), TextManager.Get("PersonalityTrait"));
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoValueGroup.RectTransform), TextManager.Get("personalitytrait." + trait.Name.Replace(" ", "")));
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoValueGroup.RectTransform), TextManager.Get("personalitytrait." + trait.Name.Replace(" ".ToIdentifier(), Identifier.Empty)));
|
||||
}
|
||||
infoLabelGroup.Recalculate();
|
||||
infoValueGroup.Recalculate();
|
||||
@@ -568,7 +581,7 @@ namespace Barotrauma
|
||||
return false;
|
||||
}
|
||||
|
||||
hireableList.Content.RemoveChild(hireableList.Content.FindChild(c => (c.UserData as Tuple<CharacterInfo, float>).Item1 == characterInfo));
|
||||
hireableList.Content.RemoveChild(hireableList.Content.FindChild(c => ((InfoSkill)c.UserData).CharacterInfo == characterInfo));
|
||||
hireableList.UpdateScrollBarSize();
|
||||
if (!PendingHires.Contains(characterInfo)) { PendingHires.Add(characterInfo); }
|
||||
CreateCharacterFrame(characterInfo, pendingList);
|
||||
@@ -582,14 +595,14 @@ namespace Barotrauma
|
||||
private bool RemovePendingHire(CharacterInfo characterInfo, bool setTotalHireCost = true, bool createNetworkMessage = true)
|
||||
{
|
||||
if (PendingHires.Contains(characterInfo)) { PendingHires.Remove(characterInfo); }
|
||||
pendingList.Content.RemoveChild(pendingList.Content.FindChild(c => (c.UserData as Tuple<CharacterInfo, float>).Item1 == characterInfo));
|
||||
pendingList.Content.RemoveChild(pendingList.Content.FindChild(c => ((InfoSkill)c.UserData).CharacterInfo == characterInfo));
|
||||
pendingList.UpdateScrollBarSize();
|
||||
|
||||
// Server will reset the names to originals in multiplayer
|
||||
if (!GameMain.IsMultiplayer) { characterInfo?.ResetName(); }
|
||||
|
||||
if (campaign.Map.CurrentLocation.HireManager.AvailableCharacters.Any(info => info.GetIdentifierUsingOriginalName() == characterInfo.GetIdentifierUsingOriginalName()) &&
|
||||
hireableList.Content.Children.None(c => c.UserData is Tuple<CharacterInfo, float> userData && userData.Item1.GetIdentifierUsingOriginalName() == characterInfo.GetIdentifierUsingOriginalName()))
|
||||
hireableList.Content.Children.None(c => c.UserData is InfoSkill userData && userData.CharacterInfo.GetIdentifierUsingOriginalName() == characterInfo.GetIdentifierUsingOriginalName()))
|
||||
{
|
||||
CreateCharacterFrame(characterInfo, hireableList);
|
||||
SortCharacters(hireableList, (SortingMethod)sortingDropDown.SelectedItemData);
|
||||
@@ -603,7 +616,7 @@ namespace Barotrauma
|
||||
|
||||
private bool RemoveAllPendingHires(bool createNetworkMessage = true)
|
||||
{
|
||||
pendingList.Content.Children.ToList().ForEach(c => RemovePendingHire((c.UserData as Tuple<CharacterInfo, float>).Item1, setTotalHireCost: false, createNetworkMessage));
|
||||
pendingList.Content.Children.ToList().ForEach(c => RemovePendingHire(((InfoSkill)c.UserData).CharacterInfo, setTotalHireCost: false, createNetworkMessage));
|
||||
SetTotalHireCost();
|
||||
return true;
|
||||
}
|
||||
@@ -614,12 +627,12 @@ namespace Barotrauma
|
||||
int total = 0;
|
||||
pendingList.Content.Children.ForEach(c =>
|
||||
{
|
||||
total += (c.UserData as Tuple<CharacterInfo, float>).Item1.Salary;
|
||||
total += ((InfoSkill)c.UserData).CharacterInfo.Salary;
|
||||
});
|
||||
totalBlock.Text = FormatCurrency(total);
|
||||
bool enoughMoney = campaign != null ? total <= campaign.Money : true;
|
||||
totalBlock.Text = TextManager.FormatCurrency(total);
|
||||
bool enoughMoney = campaign == null || campaign.Wallet.CanAfford(total);
|
||||
totalBlock.TextColor = enoughMoney ? Color.White : Color.Red;
|
||||
validateHiresButton.Enabled = enoughMoney && pendingList.Content.RectTransform.Children.Any();
|
||||
validateHiresButton.Enabled = enoughMoney && HasPermission && pendingList.Content.RectTransform.Children.Any();
|
||||
}
|
||||
|
||||
public bool ValidateHires(List<CharacterInfo> hires, bool createNetworkEvent = false)
|
||||
@@ -639,7 +652,7 @@ namespace Barotrauma
|
||||
|
||||
int total = nonDuplicateHires.Aggregate(0, (total, info) => total + info.Salary);
|
||||
|
||||
if (total > campaign.Money) { return false; }
|
||||
if (!campaign.Wallet.CanAfford(total)) { return false; }
|
||||
|
||||
bool atLeastOneHired = false;
|
||||
foreach (CharacterInfo ci in nonDuplicateHires)
|
||||
@@ -661,7 +674,7 @@ namespace Barotrauma
|
||||
var dialog = new GUIMessageBox(
|
||||
TextManager.Get("newcrewmembers"),
|
||||
TextManager.GetWithVariable("crewhiredmessage", "[location]", campaignUI?.Campaign?.Map?.CurrentLocation?.Name),
|
||||
new string[] { TextManager.Get("Ok") });
|
||||
new LocalizedString[] { TextManager.Get("Ok") });
|
||||
dialog.Buttons[0].OnClicked += dialog.Close;
|
||||
}
|
||||
|
||||
@@ -687,7 +700,7 @@ namespace Barotrauma
|
||||
RelativeSpacing = 0.02f,
|
||||
Stretch = true
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), layoutGroup.RectTransform), TextManager.Get("campaigncrew.givenickname"), font: GUI.SubHeadingFont, textAlignment: Alignment.Center, wrap: true);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), layoutGroup.RectTransform), TextManager.Get("campaigncrew.givenickname"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Center, wrap: true);
|
||||
var groupElementSize = new Vector2(1.0f, 0.25f);
|
||||
var nameBox = new GUITextBox(new RectTransform(groupElementSize, layoutGroup.RectTransform))
|
||||
{
|
||||
@@ -732,7 +745,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
var crewComponent = crewList.Content.FindChild(c => (c.UserData as Tuple<CharacterInfo, float>).Item1 == characterInfo);
|
||||
var crewComponent = crewList.Content.FindChild(c => ((InfoSkill)c.UserData).CharacterInfo == characterInfo);
|
||||
if (crewComponent != null)
|
||||
{
|
||||
crewList.Content.RemoveChild(crewComponent);
|
||||
@@ -742,7 +755,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
var pendingComponent = pendingList.Content.FindChild(c => (c.UserData as Tuple<CharacterInfo, float>).Item1 == characterInfo);
|
||||
var pendingComponent = pendingList.Content.FindChild(c => ((InfoSkill)c.UserData).CharacterInfo == characterInfo);
|
||||
if (pendingComponent != null)
|
||||
{
|
||||
pendingList.Content.RemoveChild(pendingComponent);
|
||||
@@ -821,15 +834,15 @@ namespace Barotrauma
|
||||
characterPreviewFrame = null;
|
||||
}
|
||||
|
||||
static (GUIComponent, CharacterInfo) FindHighlightedCharacter(GUIComponent c)
|
||||
static (GUIComponent GuiComponent, CharacterInfo CharacterInfo) FindHighlightedCharacter(GUIComponent c)
|
||||
{
|
||||
if (c == null)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
if (c.UserData is Tuple<CharacterInfo, float> highlightedData)
|
||||
if (c.UserData is InfoSkill highlightedData)
|
||||
{
|
||||
return (c, highlightedData.Item1);
|
||||
return (c, highlightedData.CharacterInfo);
|
||||
}
|
||||
if (c.Parent != null)
|
||||
{
|
||||
@@ -912,7 +925,5 @@ namespace Barotrauma
|
||||
GameMain.Client.ClientPeer?.Send(msg, DeliveryMethod.Reliable);
|
||||
}
|
||||
}
|
||||
|
||||
private string FormatCurrency(int currency) => TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", currency));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
#nullable enable
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Barotrauma.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Barotrauma.Extensions;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -18,7 +20,7 @@ namespace Barotrauma
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value && backgroundFrame == null) { Init(); }
|
||||
if (value) { InitIfNecessary(); }
|
||||
if (!value)
|
||||
{
|
||||
fileSystemWatcher?.Dispose();
|
||||
@@ -28,26 +30,31 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private static GUIFrame backgroundFrame;
|
||||
private static GUIFrame window;
|
||||
private static GUIListBox sidebar;
|
||||
private static GUIListBox fileList;
|
||||
private static GUITextBox directoryBox;
|
||||
private static GUITextBox filterBox;
|
||||
private static GUITextBox fileBox;
|
||||
private static GUIDropDown fileTypeDropdown;
|
||||
private static GUIButton openButton;
|
||||
private static GUIFrame? backgroundFrame;
|
||||
private static GUIFrame? window;
|
||||
private static GUIListBox? sidebar;
|
||||
private static GUIListBox? fileList;
|
||||
private static GUITextBox? directoryBox;
|
||||
private static GUITextBox? filterBox;
|
||||
private static GUITextBox? fileBox;
|
||||
private static GUIDropDown? fileTypeDropdown;
|
||||
private static GUIButton? openButton;
|
||||
|
||||
private static System.IO.FileSystemWatcher fileSystemWatcher;
|
||||
private static System.IO.FileSystemWatcher? fileSystemWatcher;
|
||||
|
||||
private static string currentFileTypePattern;
|
||||
private enum ItemIsDirectory
|
||||
{
|
||||
Yes, No
|
||||
}
|
||||
|
||||
private static readonly string[] ignoredDrivePrefixes = new string[]
|
||||
private static string? currentFileTypePattern;
|
||||
|
||||
private static readonly string[] ignoredDrivePrefixes =
|
||||
{
|
||||
"/sys/", "/snap/"
|
||||
};
|
||||
|
||||
private static string currentDirectory;
|
||||
private static string currentDirectory = "";
|
||||
public static string CurrentDirectory
|
||||
{
|
||||
get
|
||||
@@ -91,7 +98,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public static Action<string> OnFileSelected
|
||||
public static Action<string>? OnFileSelected
|
||||
{
|
||||
get;
|
||||
set;
|
||||
@@ -99,15 +106,16 @@ namespace Barotrauma
|
||||
|
||||
private static void OnFileSystemChanges(object sender, System.IO.FileSystemEventArgs e)
|
||||
{
|
||||
if (fileList is null) { return; }
|
||||
switch (e.ChangeType)
|
||||
{
|
||||
case System.IO.WatcherChangeTypes.Created:
|
||||
{
|
||||
var itemFrame = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), fileList.Content.RectTransform), e.Name)
|
||||
var itemFrame = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), fileList.Content.RectTransform), e.Name ?? string.Empty)
|
||||
{
|
||||
UserData = (bool?)Directory.Exists(e.FullPath)
|
||||
UserData = Directory.Exists(e.FullPath) ? ItemIsDirectory.Yes : ItemIsDirectory.No
|
||||
};
|
||||
if ((itemFrame.UserData as bool?) ?? false)
|
||||
if (itemFrame.UserData is ItemIsDirectory.Yes)
|
||||
{
|
||||
itemFrame.Text += "/";
|
||||
}
|
||||
@@ -122,11 +130,13 @@ namespace Barotrauma
|
||||
break;
|
||||
case System.IO.WatcherChangeTypes.Renamed:
|
||||
{
|
||||
System.IO.RenamedEventArgs renameArgs = e as System.IO.RenamedEventArgs;
|
||||
var itemFrame = fileList.Content.FindChild(c => (c is GUITextBlock tb) && (tb.Text == renameArgs.OldName || tb.Text == renameArgs.OldName + "/")) as GUITextBlock;
|
||||
itemFrame.UserData = (bool?)Directory.Exists(e.FullPath);
|
||||
itemFrame.Text = renameArgs.Name;
|
||||
if ((itemFrame.UserData as bool?) ?? false)
|
||||
System.IO.RenamedEventArgs renameArgs = e as System.IO.RenamedEventArgs ?? throw new InvalidCastException($"Unable to cast {nameof(System.IO.FileSystemEventArgs)} to {nameof(System.IO.RenamedEventArgs)}.");
|
||||
var itemFrame =
|
||||
fileList.Content.FindChild(c => (c is GUITextBlock tb) && (tb.Text == renameArgs.OldName || tb.Text == renameArgs.OldName + "/")) as GUITextBlock
|
||||
?? throw new Exception($"Could not find file list item with name \"{renameArgs.OldName}\"");
|
||||
itemFrame.UserData = Directory.Exists(e.FullPath) ? ItemIsDirectory.Yes : ItemIsDirectory.No;
|
||||
itemFrame.Text = renameArgs.Name ?? string.Empty;
|
||||
if (itemFrame.UserData is ItemIsDirectory.Yes)
|
||||
{
|
||||
itemFrame.Text += "/";
|
||||
}
|
||||
@@ -138,10 +148,10 @@ namespace Barotrauma
|
||||
|
||||
private static int SortFiles(RectTransform r1, RectTransform r2)
|
||||
{
|
||||
string file1 = (r1.GUIComponent as GUITextBlock)?.Text ?? "";
|
||||
string file2 = (r2.GUIComponent as GUITextBlock)?.Text ?? "";
|
||||
bool dir1 = (r1.GUIComponent.UserData as bool?) ?? false;
|
||||
bool dir2 = (r2.GUIComponent.UserData as bool?) ?? false;
|
||||
string file1 = (r1.GUIComponent as GUITextBlock)?.Text?.SanitizedValue ?? "";
|
||||
string file2 = (r2.GUIComponent as GUITextBlock)?.Text?.SanitizedValue ?? "";
|
||||
bool dir1 = r1.GUIComponent.UserData is ItemIsDirectory.Yes;
|
||||
bool dir2 = r2.GUIComponent.UserData is ItemIsDirectory.Yes;
|
||||
if (dir1 && !dir2)
|
||||
{
|
||||
return -1;
|
||||
@@ -154,6 +164,11 @@ namespace Barotrauma
|
||||
return string.Compare(file1, file2);
|
||||
}
|
||||
|
||||
private static void InitIfNecessary()
|
||||
{
|
||||
if (backgroundFrame == null) { Init(); }
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
backgroundFrame = new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, GUI.Canvas), style: null)
|
||||
@@ -179,7 +194,7 @@ namespace Barotrauma
|
||||
|
||||
sidebar.OnSelected = (child, userdata) =>
|
||||
{
|
||||
CurrentDirectory = (child as GUITextBlock).Text;
|
||||
CurrentDirectory = (child as GUITextBlock)?.Text.SanitizedValue ?? throw new Exception("Sidebar selection is invalid");
|
||||
|
||||
return false;
|
||||
};
|
||||
@@ -228,13 +243,14 @@ namespace Barotrauma
|
||||
{
|
||||
OnSelected = (child, userdata) =>
|
||||
{
|
||||
if (userdata == null) { return false; }
|
||||
if (userdata is null) { return false; }
|
||||
if (fileBox is null) { return false; }
|
||||
|
||||
var fileName = (child as GUITextBlock).Text;
|
||||
var fileName = (child as GUITextBlock)!.Text.SanitizedValue;
|
||||
fileBox.Text = fileName;
|
||||
if (PlayerInput.DoubleClicked())
|
||||
{
|
||||
bool isDir = (userdata as bool?).Value;
|
||||
bool isDir = userdata is ItemIsDirectory.Yes;
|
||||
if (isDir)
|
||||
{
|
||||
CurrentDirectory += fileName;
|
||||
@@ -263,7 +279,7 @@ namespace Barotrauma
|
||||
{
|
||||
OnSelected = (child, userdata) =>
|
||||
{
|
||||
currentFileTypePattern = (child as GUITextBlock).UserData as string;
|
||||
currentFileTypePattern = (child as GUITextBlock)!.UserData as string;
|
||||
RefreshFileList();
|
||||
|
||||
return true;
|
||||
@@ -307,30 +323,31 @@ namespace Barotrauma
|
||||
|
||||
public static void ClearFileTypeFilters()
|
||||
{
|
||||
if (backgroundFrame == null) { Init(); }
|
||||
fileTypeDropdown.ClearChildren();
|
||||
InitIfNecessary();
|
||||
fileTypeDropdown!.ClearChildren();
|
||||
}
|
||||
|
||||
public static void AddFileTypeFilter(string name, string pattern)
|
||||
{
|
||||
if (backgroundFrame == null) { Init(); }
|
||||
fileTypeDropdown.AddItem(name + " (" + pattern + ")", pattern);
|
||||
InitIfNecessary();
|
||||
fileTypeDropdown!.AddItem(name + " (" + pattern + ")", pattern);
|
||||
}
|
||||
|
||||
public static void SelectFileTypeFilter(string pattern)
|
||||
{
|
||||
if (backgroundFrame == null) { Init(); }
|
||||
fileTypeDropdown.SelectItem(pattern);
|
||||
InitIfNecessary();
|
||||
fileTypeDropdown!.SelectItem(pattern);
|
||||
}
|
||||
|
||||
public static void RefreshFileList()
|
||||
{
|
||||
fileList.Content.ClearChildren();
|
||||
InitIfNecessary();
|
||||
fileList!.Content.ClearChildren();
|
||||
fileList.BarScroll = 0.0f;
|
||||
|
||||
try
|
||||
{
|
||||
var directories = Directory.EnumerateDirectories(currentDirectory, "*" + filterBox.Text + "*");
|
||||
var directories = Directory.EnumerateDirectories(currentDirectory, "*" + filterBox!.Text + "*");
|
||||
foreach (var directory in directories)
|
||||
{
|
||||
string txt = directory;
|
||||
@@ -338,7 +355,7 @@ namespace Barotrauma
|
||||
if (!txt.EndsWith("/")) { txt += "/"; }
|
||||
var itemFrame = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), fileList.Content.RectTransform), txt)
|
||||
{
|
||||
UserData = (bool?)true
|
||||
UserData = ItemIsDirectory.Yes
|
||||
};
|
||||
var folderIcon = new GUIImage(new RectTransform(new Point((int)(itemFrame.Rect.Height * 0.8f)), itemFrame.RectTransform, Anchor.CenterLeft)
|
||||
{
|
||||
@@ -347,18 +364,18 @@ namespace Barotrauma
|
||||
itemFrame.Padding = new Vector4(folderIcon.Rect.Width * 1.5f, itemFrame.Padding.Y, itemFrame.Padding.Z, itemFrame.Padding.W);
|
||||
}
|
||||
|
||||
IEnumerable<string> files = null;
|
||||
if (currentFileTypePattern == null)
|
||||
IEnumerable<string> files = Enumerable.Empty<string>();
|
||||
if (currentFileTypePattern.IsNullOrEmpty())
|
||||
{
|
||||
files = Directory.GetFiles(currentDirectory);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (string pattern in currentFileTypePattern.Split(','))
|
||||
foreach (string pattern in currentFileTypePattern!.Split(','))
|
||||
{
|
||||
string patternTrimmed = pattern.Trim();
|
||||
patternTrimmed = "*" + filterBox.Text + "*" + patternTrimmed;
|
||||
if (files == null)
|
||||
if (files.None())
|
||||
{
|
||||
files = Directory.EnumerateFiles(currentDirectory, patternTrimmed);
|
||||
}
|
||||
@@ -375,7 +392,7 @@ namespace Barotrauma
|
||||
if (txt.StartsWith(currentDirectory)) { txt = txt.Substring(currentDirectory.Length); }
|
||||
var itemFrame = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), fileList.Content.RectTransform), txt)
|
||||
{
|
||||
UserData = (bool?)false
|
||||
UserData = ItemIsDirectory.No
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -387,8 +404,8 @@ namespace Barotrauma
|
||||
};
|
||||
}
|
||||
|
||||
directoryBox.Text = currentDirectory;
|
||||
fileBox.Text = "";
|
||||
directoryBox!.Text = currentDirectory;
|
||||
fileBox!.Text = "";
|
||||
fileList.Deselect();
|
||||
}
|
||||
|
||||
@@ -398,9 +415,9 @@ namespace Barotrauma
|
||||
if (dir.EndsWith("/")) { dir = dir.Substring(0, dir.Length - 1); }
|
||||
int index = dir.LastIndexOf("/");
|
||||
if (index < 0) { return false; }
|
||||
CurrentDirectory = CurrentDirectory.Substring(0, index+1);
|
||||
CurrentDirectory = CurrentDirectory.Substring(0, index + 1);
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void AddToGUIUpdateList()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -116,32 +116,32 @@ namespace Barotrauma
|
||||
get { return Frame.FlashTimer; }
|
||||
}
|
||||
|
||||
public override ScalableFont Font
|
||||
public override GUIFont Font
|
||||
{
|
||||
get
|
||||
{
|
||||
return (textBlock == null) ? GUI.Font : textBlock.Font;
|
||||
return (textBlock == null) ? GUIStyle.Font : textBlock.Font;
|
||||
}
|
||||
set
|
||||
{
|
||||
base.Font = value;
|
||||
if (textBlock != null) textBlock.Font = value;
|
||||
if (textBlock != null) { textBlock.Font = value; }
|
||||
}
|
||||
}
|
||||
|
||||
public string Text
|
||||
public LocalizedString Text
|
||||
{
|
||||
get { return textBlock.Text; }
|
||||
set { textBlock.Text = value; }
|
||||
}
|
||||
|
||||
public bool ForceUpperCase
|
||||
public ForceUpperCase ForceUpperCase
|
||||
{
|
||||
get { return textBlock.ForceUpperCase; }
|
||||
set { textBlock.ForceUpperCase = value; }
|
||||
}
|
||||
|
||||
public override string ToolTip
|
||||
public override RichString ToolTip
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -160,39 +160,36 @@ namespace Barotrauma
|
||||
private bool flashed;
|
||||
|
||||
public GUISoundType ClickSound { get; set; } = GUISoundType.Click;
|
||||
|
||||
public GUIButton(RectTransform rectT, string text = "", Alignment textAlignment = Alignment.Center, string style = "", Color? color = null) : base(style, rectT)
|
||||
|
||||
public GUIButton(RectTransform rectT, Alignment textAlignment = Alignment.Center, string style = "", Color? color = null) : this(rectT, new RawLString(""), textAlignment, style, color) { }
|
||||
|
||||
public GUIButton(RectTransform rectT, LocalizedString text, Alignment textAlignment = Alignment.Center, string style = "", Color? color = null) : base(style, rectT)
|
||||
{
|
||||
CanBeFocused = true;
|
||||
HoverCursor = CursorState.Hand;
|
||||
|
||||
frame = new GUIFrame(new RectTransform(Vector2.One, rectT), style) { CanBeFocused = false };
|
||||
if (style != null) { GUI.Style.Apply(frame, style == "" ? "GUIButton" : style); }
|
||||
if (style != null) { GUIStyle.Apply(frame, style == "" ? "GUIButton" : style); }
|
||||
if (color.HasValue)
|
||||
{
|
||||
this.color = frame.Color = color.Value;
|
||||
}
|
||||
|
||||
var selfStyle = Style;
|
||||
textBlock = new GUITextBlock(new RectTransform(Vector2.One, rectT, Anchor.Center), text, textAlignment: textAlignment, style: null)
|
||||
{
|
||||
TextColor = this.style == null ? Color.Black : this.style.TextColor,
|
||||
HoverTextColor = this.style == null ? Color.Black : this.style.HoverTextColor,
|
||||
SelectedTextColor = this.style == null ? Color.Black : this.style.SelectedTextColor,
|
||||
TextColor = selfStyle?.TextColor ?? Color.Black,
|
||||
HoverTextColor = selfStyle?.HoverTextColor ?? Color.Black,
|
||||
SelectedTextColor = selfStyle?.SelectedTextColor ?? Color.Black,
|
||||
CanBeFocused = false
|
||||
};
|
||||
if (rectT.Rect.Height == 0 && !string.IsNullOrEmpty(text))
|
||||
if (rectT.Rect.Height == 0 && !text.IsNullOrEmpty())
|
||||
{
|
||||
RectTransform.Resize(new Point(RectTransform.Rect.Width, (int)Font.MeasureString(textBlock.Text).Y));
|
||||
RectTransform.MinSize = textBlock.RectTransform.MinSize = new Point(0, System.Math.Max(rectT.MinSize.Y, Rect.Height));
|
||||
TextBlock.SetTextPos();
|
||||
}
|
||||
GUI.Style.Apply(textBlock, "", this);
|
||||
|
||||
//if the text is in chinese/korean/japanese and we're not using a CJK-compatible font,
|
||||
//use the default CJK font as a fallback
|
||||
if (TextManager.IsCJK(textBlock.Text) && !textBlock.Font.IsCJK)
|
||||
{
|
||||
textBlock.Font = GUI.CJKFont;
|
||||
}
|
||||
GUIStyle.Apply(textBlock, "", this);
|
||||
|
||||
Enabled = true;
|
||||
}
|
||||
@@ -217,7 +214,7 @@ namespace Barotrauma
|
||||
float expand = (pulseExpand * 20.0f) * GUI.Scale;
|
||||
expandRect.Inflate(expand, expand);
|
||||
|
||||
GUI.Style.ButtonPulse.Draw(spriteBatch, expandRect, ToolBox.GradientLerp(pulseExpand, Color.White, Color.White, Color.Transparent));
|
||||
GUIStyle.EndRoundButtonPulse.Draw(spriteBatch, expandRect, ToolBox.GradientLerp(pulseExpand, Color.White, Color.White, Color.Transparent));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class GUIColorPicker : GUIComponent
|
||||
public class GUIColorPicker : GUIComponent, IDisposable
|
||||
{
|
||||
public delegate bool OnColorSelectedHandler(GUIColorPicker component, Color color);
|
||||
public OnColorSelectedHandler? OnColorSelected;
|
||||
@@ -34,11 +34,6 @@ namespace Barotrauma
|
||||
|
||||
public GUIColorPicker(RectTransform rectT, string? style = null) : base(style, rectT) { }
|
||||
|
||||
~GUIColorPicker()
|
||||
{
|
||||
DisposeTextures();
|
||||
}
|
||||
|
||||
private void Init()
|
||||
{
|
||||
int tWidth = Rect.Width;
|
||||
@@ -170,10 +165,12 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public void DisposeTextures()
|
||||
public void Dispose()
|
||||
{
|
||||
mainTexture?.Dispose();
|
||||
mainTexture = null;
|
||||
hueTexture?.Dispose();
|
||||
hueTexture = null;
|
||||
}
|
||||
|
||||
public void RefreshHue()
|
||||
|
||||
@@ -8,6 +8,7 @@ using System.Xml.Linq;
|
||||
using Barotrauma.IO;
|
||||
using RestSharp;
|
||||
using System.Net;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -39,7 +40,7 @@ namespace Barotrauma
|
||||
|
||||
public IEnumerable<T> GetAllChildren<T>() where T : GUIComponent
|
||||
{
|
||||
return GetAllChildren().Where(c => c is T).Select(c => c as T);
|
||||
return GetAllChildren().OfType<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -66,7 +67,7 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (GUIComponent child in Children)
|
||||
{
|
||||
if (child.UserData == obj || (child.userData != null && child.userData.Equals(obj))) { return child; }
|
||||
if (Equals(child.UserData, obj)) { return child; }
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -107,7 +108,7 @@ namespace Barotrauma
|
||||
}
|
||||
public GUIComponent FindChild(object userData, bool recursive = false)
|
||||
{
|
||||
var matchingChild = Children.FirstOrDefault(c => c.userData == userData);
|
||||
var matchingChild = Children.FirstOrDefault(c => Equals(c.UserData, userData));
|
||||
if (recursive && matchingChild == null)
|
||||
{
|
||||
foreach (GUIComponent child in Children)
|
||||
@@ -122,7 +123,7 @@ namespace Barotrauma
|
||||
|
||||
public IEnumerable<GUIComponent> FindChildren(object userData)
|
||||
{
|
||||
return Children.Where(c => c.userData == userData);
|
||||
return Children.Where(c => Equals(c.UserData, userData));
|
||||
}
|
||||
|
||||
public IEnumerable<GUIComponent> FindChildren(Func<GUIComponent, bool> predicate)
|
||||
@@ -161,9 +162,7 @@ namespace Barotrauma
|
||||
|
||||
protected Alignment alignment;
|
||||
|
||||
protected GUIComponentStyle style;
|
||||
|
||||
protected object userData;
|
||||
protected Identifier[] styleHierarchy;
|
||||
|
||||
public bool CanBeFocused;
|
||||
|
||||
@@ -206,16 +205,14 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public virtual ScalableFont Font
|
||||
public virtual GUIFont Font
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
// Use the rawtooltip when copying displayed tooltips so that any possible color-data related values are translated over as well
|
||||
public string RawToolTip;
|
||||
private string toolTip;
|
||||
public virtual string ToolTip
|
||||
|
||||
private RichString toolTip;
|
||||
public virtual RichString ToolTip
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -223,18 +220,12 @@ namespace Barotrauma
|
||||
}
|
||||
set
|
||||
{
|
||||
RawToolTip = value;
|
||||
TooltipRichTextData = RichTextData.GetRichTextData(value, out value);
|
||||
toolTip = value;
|
||||
}
|
||||
}
|
||||
|
||||
public List<RichTextData> TooltipRichTextData = null;
|
||||
|
||||
public GUIComponentStyle Style
|
||||
{
|
||||
get { return style; }
|
||||
}
|
||||
=> GUIComponentStyle.FromHierarchy(styleHierarchy);
|
||||
|
||||
public bool Visible
|
||||
{
|
||||
@@ -258,8 +249,8 @@ namespace Barotrauma
|
||||
|
||||
protected Rectangle ClampRect(Rectangle r)
|
||||
{
|
||||
if (Parent == null || !ClampMouseRectToParent) { return r; }
|
||||
Rectangle parentRect = Parent.ClampRect(Parent.Rect);
|
||||
if (Parent is null) { return r; }
|
||||
Rectangle parentRect = !Parent.ClampMouseRectToParent ? Parent.Rect : Parent.ClampRect(Parent.Rect);
|
||||
if (parentRect.Width <= 0 || parentRect.Height <= 0) { return Rectangle.Empty; }
|
||||
if (parentRect.X > r.X)
|
||||
{
|
||||
@@ -293,11 +284,13 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
public bool ClampMouseRectToParent { get; set; } = false;
|
||||
|
||||
public virtual Rectangle MouseRect
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!CanBeFocused) { return Rectangle.Empty; }
|
||||
|
||||
return ClampMouseRectToParent ? ClampRect(Rect) : Rect;
|
||||
}
|
||||
}
|
||||
@@ -310,13 +303,13 @@ namespace Barotrauma
|
||||
|
||||
protected ComponentState _state;
|
||||
protected ComponentState _previousState;
|
||||
protected bool selected;
|
||||
protected bool isSelected;
|
||||
public virtual bool Selected
|
||||
{
|
||||
get { return selected; }
|
||||
get { return isSelected; }
|
||||
set
|
||||
{
|
||||
selected = value;
|
||||
isSelected = value;
|
||||
foreach (var child in Children)
|
||||
{
|
||||
child.Selected = value;
|
||||
@@ -338,11 +331,8 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public object UserData
|
||||
{
|
||||
get { return userData; }
|
||||
set { userData = value; }
|
||||
}
|
||||
#warning TODO: this is cursed, stop using this
|
||||
public object UserData;
|
||||
|
||||
public int CountChildren
|
||||
{
|
||||
@@ -417,20 +407,20 @@ namespace Barotrauma
|
||||
|
||||
Visible = true;
|
||||
OutlineColor = Color.Transparent;
|
||||
Font = GUI.Font;
|
||||
Font = GUIStyle.Font;
|
||||
CanBeFocused = true;
|
||||
|
||||
if (style != null) { GUI.Style.Apply(this, style); }
|
||||
if (style != null) { GUIStyle.Apply(this, style); }
|
||||
}
|
||||
|
||||
protected GUIComponent(string style)
|
||||
{
|
||||
Visible = true;
|
||||
OutlineColor = Color.Transparent;
|
||||
Font = GUI.Font;
|
||||
Font = GUIStyle.Font;
|
||||
CanBeFocused = true;
|
||||
|
||||
if (style != null) { GUI.Style.Apply(this, style); }
|
||||
if (style != null) { GUIStyle.Apply(this, style); }
|
||||
}
|
||||
|
||||
#region Updating
|
||||
@@ -486,7 +476,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (GUI.IsMouseOn(this) && PlayerInput.SecondaryMouseButtonClicked())
|
||||
{
|
||||
OnSecondaryClicked?.Invoke(this, userData);
|
||||
OnSecondaryClicked?.Invoke(this, UserData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -704,7 +694,7 @@ namespace Barotrauma
|
||||
|
||||
if (GlowOnSelect && State == ComponentState.Selected)
|
||||
{
|
||||
GUI.UIGlow.Draw(spriteBatch, Rect, SelectedColor);
|
||||
GUIStyle.UIGlow.Draw(spriteBatch, Rect, SelectedColor);
|
||||
}
|
||||
|
||||
if (flashTimer > 0.0f)
|
||||
@@ -724,7 +714,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
var glow = useCircularFlash ? GUI.UIGlowCircular : GUI.UIGlow;
|
||||
var glow = useCircularFlash ? GUIStyle.UIGlowCircular : GUIStyle.UIGlow;
|
||||
glow.Draw(spriteBatch,
|
||||
flashRect,
|
||||
flashColor * (float)Math.Sin(flashTimer % flashCycleDuration / flashCycleDuration * MathHelper.Pi * 0.8f));
|
||||
@@ -738,24 +728,24 @@ namespace Barotrauma
|
||||
public void DrawToolTip(SpriteBatch spriteBatch)
|
||||
{
|
||||
if (!Visible) { return; }
|
||||
DrawToolTip(spriteBatch, ToolTip, GUI.MouseOn.Rect, TooltipRichTextData);
|
||||
DrawToolTip(spriteBatch, ToolTip, GUI.MouseOn.Rect);
|
||||
}
|
||||
|
||||
public static void DrawToolTip(SpriteBatch spriteBatch, string toolTip, Vector2 pos, List<RichTextData> richTextData = null)
|
||||
public static void DrawToolTip(SpriteBatch spriteBatch, RichString toolTip, Vector2 pos)
|
||||
{
|
||||
if (Tutorials.Tutorial.ContentRunning) { return; }
|
||||
if (GameMain.GameSession?.GameMode is TutorialMode tutorialMode && tutorialMode.Tutorial.ContentRunning) { return; }
|
||||
|
||||
int width = (int)(400 * GUI.Scale);
|
||||
int height = (int)(18 * GUI.Scale);
|
||||
Point padding = new Point((int)(10 * GUI.Scale));
|
||||
|
||||
if (toolTipBlock == null || (string)toolTipBlock.userData != toolTip)
|
||||
if (toolTipBlock == null || (RichString)toolTipBlock.UserData != toolTip)
|
||||
{
|
||||
toolTipBlock = new GUITextBlock(new RectTransform(new Point(width, height), null), richTextData, toolTip, font: GUI.SmallFont, wrap: true, style: "GUIToolTip");
|
||||
toolTipBlock = new GUITextBlock(new RectTransform(new Point(width, height), null), toolTip, font: GUIStyle.SmallFont, wrap: true, style: "GUIToolTip");
|
||||
toolTipBlock.RectTransform.NonScaledSize = new Point(
|
||||
(int)(GUI.SmallFont.MeasureString(toolTipBlock.WrappedText).X + padding.X + toolTipBlock.Padding.X + toolTipBlock.Padding.Z),
|
||||
(int)(GUI.SmallFont.MeasureString(toolTipBlock.WrappedText).Y + padding.Y + toolTipBlock.Padding.Y + toolTipBlock.Padding.W));
|
||||
toolTipBlock.userData = toolTip;
|
||||
(int)(GUIStyle.SmallFont.MeasureString(toolTipBlock.WrappedText).X + padding.X + toolTipBlock.Padding.X + toolTipBlock.Padding.Z),
|
||||
(int)(GUIStyle.SmallFont.MeasureString(toolTipBlock.WrappedText).Y + padding.Y + toolTipBlock.Padding.Y + toolTipBlock.Padding.W));
|
||||
toolTipBlock.UserData = toolTip;
|
||||
}
|
||||
|
||||
toolTipBlock.RectTransform.AbsoluteOffset = pos.ToPoint();
|
||||
@@ -764,21 +754,21 @@ namespace Barotrauma
|
||||
toolTipBlock.DrawManually(spriteBatch);
|
||||
}
|
||||
|
||||
public static void DrawToolTip(SpriteBatch spriteBatch, string toolTip, Rectangle targetElement, List<RichTextData> richTextData = null)
|
||||
public static void DrawToolTip(SpriteBatch spriteBatch, RichString toolTip, Rectangle targetElement)
|
||||
{
|
||||
if (Tutorials.Tutorial.ContentRunning) { return; }
|
||||
if (GameMain.GameSession?.GameMode is TutorialMode tutorialMode && tutorialMode.Tutorial.ContentRunning) { return; }
|
||||
|
||||
int width = (int)(400 * GUI.Scale);
|
||||
int height = (int)(18 * GUI.Scale);
|
||||
Point padding = new Point((int)(10 * GUI.Scale));
|
||||
|
||||
if (toolTipBlock == null || (string)toolTipBlock.userData != toolTip)
|
||||
if (toolTipBlock == null || (RichString)toolTipBlock.UserData != toolTip)
|
||||
{
|
||||
toolTipBlock = new GUITextBlock(new RectTransform(new Point(width, height), null), richTextData, toolTip, font: GUI.SmallFont, wrap: true, style: "GUIToolTip");
|
||||
toolTipBlock = new GUITextBlock(new RectTransform(new Point(width, height), null), toolTip, font: GUIStyle.SmallFont, wrap: true, style: "GUIToolTip");
|
||||
toolTipBlock.RectTransform.NonScaledSize = new Point(
|
||||
(int)(toolTipBlock.Font.MeasureString(toolTipBlock.WrappedText).X + padding.X + toolTipBlock.Padding.X + toolTipBlock.Padding.Z),
|
||||
(int)(toolTipBlock.Font.MeasureString(toolTipBlock.WrappedText).Y + padding.Y + toolTipBlock.Padding.Y + toolTipBlock.Padding.W));
|
||||
toolTipBlock.userData = toolTip;
|
||||
toolTipBlock.UserData = toolTip;
|
||||
}
|
||||
|
||||
toolTipBlock.RectTransform.AbsoluteOffset = new Point(targetElement.Center.X, targetElement.Bottom);
|
||||
@@ -811,7 +801,7 @@ namespace Barotrauma
|
||||
this.useRectangleFlash = useRectangleFlash;
|
||||
this.useCircularFlash = useCircularFlash;
|
||||
this.flashDuration = flashDuration;
|
||||
flashColor = (color == null) ? GUI.Style.Red : (Color)color;
|
||||
flashColor = (color == null) ? GUIStyle.Red : (Color)color;
|
||||
}
|
||||
|
||||
public void FadeOut(float duration, bool removeAfter, float wait = 0.0f)
|
||||
@@ -952,8 +942,7 @@ namespace Barotrauma
|
||||
ApplySizeRestrictions(style);
|
||||
}
|
||||
|
||||
|
||||
this.style = style;
|
||||
styleHierarchy = GUIComponentStyle.ToHierarchy(style);
|
||||
}
|
||||
|
||||
public void ApplySizeRestrictions(GUIComponentStyle style)
|
||||
@@ -972,11 +961,11 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public static GUIComponent FromXML(XElement element, RectTransform parent)
|
||||
public static GUIComponent FromXML(ContentXElement element, RectTransform parent)
|
||||
{
|
||||
GUIComponent component = null;
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
if (subElement.Name.ToString().Equals("conditional", StringComparison.OrdinalIgnoreCase) && !CheckConditional(subElement))
|
||||
{
|
||||
@@ -1027,7 +1016,7 @@ namespace Barotrauma
|
||||
|
||||
if (component != null)
|
||||
{
|
||||
foreach (XElement subElement in element.Elements())
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
if (subElement.Name.ToString().Equals("conditional", StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||
FromXML(subElement, component is GUIListBox listBox ? listBox.Content.RectTransform : component.RectTransform);
|
||||
@@ -1078,8 +1067,9 @@ namespace Barotrauma
|
||||
switch (attribute.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "language":
|
||||
string[] languages = element.GetAttributeStringArray(attribute.Name.ToString(), new string[0]);
|
||||
if (!languages.Any(l => GameMain.Config.Language.Equals(l, StringComparison.OrdinalIgnoreCase))) { return false; }
|
||||
var languages = element.GetAttributeIdentifierArray(attribute.Name.ToString(), Array.Empty<Identifier>())
|
||||
.Select(s => new LanguageIdentifier(s));
|
||||
if (!languages.Any(l => GameSettings.CurrentConfig.Language == l)) { return false; }
|
||||
break;
|
||||
case "gameversion":
|
||||
var version = new Version(attribute.Value);
|
||||
@@ -1136,23 +1126,12 @@ namespace Barotrauma
|
||||
if (element.Attribute("color") != null) { color = element.GetAttributeColor("color", Color.White); }
|
||||
float scale = element.GetAttributeFloat("scale", 1.0f);
|
||||
bool wrap = element.GetAttributeBool("wrap", true);
|
||||
Alignment alignment = Alignment.Center;
|
||||
Enum.TryParse(element.GetAttributeString("alignment", "Center"), out alignment);
|
||||
ScalableFont font = GUI.Font;
|
||||
switch (element.GetAttributeString("font", "Font").ToLowerInvariant())
|
||||
Alignment alignment =
|
||||
element.GetAttributeEnum("alignment", text.Contains('\n') ? Alignment.Left : Alignment.Center);
|
||||
GUIFont font;
|
||||
if (!GUIStyle.Fonts.TryGetValue(element.GetAttributeIdentifier("font", "Font"), out font))
|
||||
{
|
||||
case "font":
|
||||
font = GUI.Font;
|
||||
break;
|
||||
case "smallfont":
|
||||
font = GUI.SmallFont;
|
||||
break;
|
||||
case "largefont":
|
||||
font = GUI.LargeFont;
|
||||
break;
|
||||
case "subheading":
|
||||
font = GUI.SubHeadingFont;
|
||||
break;
|
||||
font = GUIStyle.Font;
|
||||
}
|
||||
|
||||
var textBlock = new GUITextBlock(RectTransform.Load(element, parent),
|
||||
@@ -1265,7 +1244,7 @@ namespace Barotrauma
|
||||
};
|
||||
}
|
||||
|
||||
private static GUIImage LoadGUIImage(XElement element, RectTransform parent)
|
||||
private static GUIImage LoadGUIImage(ContentXElement element, RectTransform parent)
|
||||
{
|
||||
Sprite sprite;
|
||||
string url = element.GetAttributeString("url", "");
|
||||
@@ -1298,11 +1277,11 @@ namespace Barotrauma
|
||||
return new GUIImage(RectTransform.Load(element, parent), sprite, scaleToFit: true);
|
||||
}
|
||||
|
||||
private static GUIButton LoadAccordion(XElement element, RectTransform parent)
|
||||
private static GUIButton LoadAccordion(ContentXElement element, RectTransform parent)
|
||||
{
|
||||
var button = LoadGUIButton(element, parent);
|
||||
List<GUIComponent> content = new List<GUIComponent>();
|
||||
foreach (XElement subElement in element.Elements())
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
var contentElement = FromXML(subElement, parent);
|
||||
if (contentElement != null)
|
||||
|
||||
@@ -9,16 +9,23 @@ namespace Barotrauma
|
||||
{
|
||||
struct ContextMenuOption
|
||||
{
|
||||
public string Label;
|
||||
public LocalizedString Label;
|
||||
public Action OnSelected;
|
||||
public ContextMenuOption[]? SubOptions;
|
||||
public bool IsEnabled;
|
||||
public string Tooltip;
|
||||
public LocalizedString Tooltip;
|
||||
|
||||
|
||||
// Creates a regular context menu
|
||||
public ContextMenuOption(string label, bool isEnabled, Action onSelected)
|
||||
: this(TextManager.Get(label).Fallback(label), isEnabled, onSelected) { }
|
||||
|
||||
public ContextMenuOption(Identifier labelTag, bool isEnabled, Action onSelected)
|
||||
: this(TextManager.Get(labelTag), isEnabled, onSelected) { }
|
||||
|
||||
// Creates a regular context menu
|
||||
public ContextMenuOption(LocalizedString label, bool isEnabled, Action onSelected)
|
||||
{
|
||||
Label = TextManager.Get(label, returnNull: true) ?? label;
|
||||
Label = label;
|
||||
OnSelected = onSelected;
|
||||
IsEnabled = isEnabled;
|
||||
SubOptions = null;
|
||||
@@ -49,14 +56,14 @@ namespace Barotrauma
|
||||
/// <param name="header">Header text</param>
|
||||
/// <param name="style">Background style</param>
|
||||
/// <param name="options">list of context menu options</param>
|
||||
public GUIContextMenu(Vector2? position, string header, string style, params ContextMenuOption[] options) : base(style, new RectTransform(Point.Zero, GUI.Canvas))
|
||||
public GUIContextMenu(Vector2? position, LocalizedString header, string style, params ContextMenuOption[] options) : base(style, new RectTransform(Point.Zero, GUI.Canvas))
|
||||
{
|
||||
Vector2 pos = position ?? PlayerInput.MousePosition;
|
||||
ScalableFont headerFont = GUI.SubHeadingFont;
|
||||
ScalableFont font = GUI.SmallFont; // font the context menu options use
|
||||
GUIFont headerFont = GUIStyle.SubHeadingFont;
|
||||
GUIFont font = GUIStyle.SmallFont; // font the context menu options use
|
||||
Vector4 padding = new Vector4(4), headerPadding = new Vector4(8);
|
||||
int horizontalPadding = (int) (padding.X + padding.Z), verticalPadding = (int) (padding.Y + padding.W);
|
||||
bool hasHeader = !string.IsNullOrWhiteSpace(header);
|
||||
bool hasHeader = !header.IsNullOrWhiteSpace();
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Estimate the size of the context menu
|
||||
@@ -88,14 +95,21 @@ namespace Barotrauma
|
||||
// Construct the GUI elements
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
GUILayoutGroup background = new GUILayoutGroup(new RectTransform(Vector2.One, RectTransform, Anchor.Center));
|
||||
GUILayoutGroup background = new GUILayoutGroup(new RectTransform(Vector2.One, RectTransform, Anchor.Center))
|
||||
{
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
Point listSize = estimatedSize;
|
||||
if (hasHeader)
|
||||
{
|
||||
HeaderLabel = new GUITextBlock(new RectTransform(new Vector2(1f, 0.2f), background.RectTransform), header, font: headerFont) { Padding = headerPadding };
|
||||
Point sz = Point.Zero;
|
||||
InflateSize(ref sz, header, headerFont);
|
||||
listSize.Y -= sz.Y;
|
||||
HeaderLabel = new GUITextBlock(new RectTransform(sz, background.RectTransform), header, font: headerFont) { Padding = headerPadding };
|
||||
}
|
||||
|
||||
GUIListBox optionList = new GUIListBox(new RectTransform(new Vector2(1f, hasHeader ? 0.8f : 1f), background.RectTransform), style: null)
|
||||
GUIListBox optionList = new GUIListBox(new RectTransform(listSize, background.RectTransform), style: null)
|
||||
{
|
||||
AutoHideScrollBar = false,
|
||||
ScrollBarVisible = false,
|
||||
@@ -111,7 +125,7 @@ namespace Barotrauma
|
||||
};
|
||||
Options.Add(option, optionElement);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(option.Tooltip) && optionElement.Enabled)
|
||||
if (!option.Tooltip.IsNullOrWhiteSpace() && optionElement.Enabled)
|
||||
{
|
||||
optionElement.ToolTip = option.Tooltip;
|
||||
}
|
||||
@@ -179,7 +193,7 @@ namespace Barotrauma
|
||||
|
||||
public static GUIContextMenu CreateContextMenu(params ContextMenuOption[] options) => CreateContextMenu(PlayerInput.MousePosition, string.Empty, null, options);
|
||||
|
||||
public static GUIContextMenu CreateContextMenu(Vector2? pos, string header, Color? headerColor, params ContextMenuOption[] options)
|
||||
public static GUIContextMenu CreateContextMenu(Vector2? pos, LocalizedString header, Color? headerColor, params ContextMenuOption[] options)
|
||||
{
|
||||
GUIContextMenu menu = new GUIContextMenu(pos,header, "GUIToolTip", options);
|
||||
if (headerColor != null)
|
||||
@@ -209,7 +223,7 @@ namespace Barotrauma
|
||||
/// <param name="label">String whose size to inflate by</param>
|
||||
/// <param name="font">What font to use</param>
|
||||
/// <returns>The size of the text</returns>
|
||||
private Vector2 InflateSize(ref Point size, string label, ScalableFont font)
|
||||
private Vector2 InflateSize(ref Point size, LocalizedString label, ScalableFont font)
|
||||
{
|
||||
Vector2 textSize = font.MeasureString(label);
|
||||
size.X = Math.Max((int) Math.Ceiling(textSize.X), size.X);
|
||||
|
||||
@@ -55,9 +55,8 @@ namespace Barotrauma
|
||||
{
|
||||
get { return listBox.SelectedComponent; }
|
||||
}
|
||||
|
||||
// TODO: fix implicit hiding
|
||||
public bool Selected
|
||||
|
||||
public override bool Selected
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -97,7 +96,7 @@ namespace Barotrauma
|
||||
set { button.TextColor = value; }
|
||||
}
|
||||
|
||||
public override ScalableFont Font
|
||||
public override GUIFont Font
|
||||
{
|
||||
get { return button?.Font ?? base.Font; }
|
||||
set
|
||||
@@ -142,13 +141,13 @@ namespace Barotrauma
|
||||
get { return selectedIndexMultiple; }
|
||||
}
|
||||
|
||||
public string Text
|
||||
public LocalizedString Text
|
||||
{
|
||||
get { return button.Text; }
|
||||
set { button.Text = value; }
|
||||
}
|
||||
|
||||
public override string ToolTip
|
||||
public override RichString ToolTip
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -162,18 +161,21 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public GUIDropDown(RectTransform rectT, string text = "", int elementCount = 4, string style = "", bool selectMultiple = false, bool dropAbove = false) : base(style, rectT)
|
||||
public GUIDropDown(RectTransform rectT, LocalizedString text = null, int elementCount = 4, string style = "", bool selectMultiple = false, bool dropAbove = false, Alignment textAlignment = Alignment.CenterLeft) : base(style, rectT)
|
||||
{
|
||||
text ??= new RawLString("");
|
||||
|
||||
HoverCursor = CursorState.Hand;
|
||||
CanBeFocused = true;
|
||||
|
||||
this.selectMultiple = selectMultiple;
|
||||
|
||||
button = new GUIButton(new RectTransform(Vector2.One, rectT), text, Alignment.CenterLeft, style: "GUIDropDown")
|
||||
button = new GUIButton(new RectTransform(Vector2.One, rectT), text, textAlignment, style: "GUIDropDown")
|
||||
{
|
||||
OnClicked = OnClicked
|
||||
OnClicked = OnClicked,
|
||||
TextBlock = { OverflowClip = true }
|
||||
};
|
||||
GUI.Style.Apply(button, "", this);
|
||||
GUIStyle.Apply(button, "", this);
|
||||
button.TextBlock.SetTextPos();
|
||||
|
||||
Anchor listAnchor = dropAbove ? Anchor.TopCenter : Anchor.BottomCenter;
|
||||
@@ -184,13 +186,13 @@ namespace Barotrauma
|
||||
Enabled = !selectMultiple
|
||||
};
|
||||
if (!selectMultiple) { listBox.OnSelected = SelectItem; }
|
||||
GUI.Style.Apply(listBox, "GUIListBox", this);
|
||||
GUI.Style.Apply(listBox.ContentBackground, "GUIListBox", this);
|
||||
GUIStyle.Apply(listBox, "GUIListBox", this);
|
||||
GUIStyle.Apply(listBox.ContentBackground, "GUIListBox", this);
|
||||
|
||||
if (button.Style.ChildStyles.ContainsKey("dropdownicon"))
|
||||
if (button.Style.ChildStyles.ContainsKey("dropdownicon".ToIdentifier()))
|
||||
{
|
||||
icon = new GUIImage(new RectTransform(new Vector2(0.6f, 0.6f), button.RectTransform, Anchor.CenterRight, scaleBasis: ScaleBasis.BothHeight) { AbsoluteOffset = new Point(5, 0) }, null, scaleToFit: true);
|
||||
icon.ApplyStyle(button.Style.ChildStyles["dropdownicon"]);
|
||||
icon.ApplyStyle(button.Style.ChildStyles["dropdownicon".ToIdentifier()]);
|
||||
}
|
||||
|
||||
currentHighestParent = FindHighestParent();
|
||||
@@ -244,8 +246,9 @@ namespace Barotrauma
|
||||
return parentHierarchy.Last();
|
||||
}
|
||||
|
||||
public void AddItem(string text, object userData = null, string toolTip = "")
|
||||
public void AddItem(LocalizedString text, object userData = null, LocalizedString toolTip = null)
|
||||
{
|
||||
toolTip ??= "";
|
||||
if (selectMultiple)
|
||||
{
|
||||
var frame = new GUIFrame(new RectTransform(new Point(button.Rect.Width, button.Rect.Height), listBox.Content.RectTransform)
|
||||
@@ -261,7 +264,7 @@ namespace Barotrauma
|
||||
ToolTip = toolTip,
|
||||
OnSelected = (GUITickBox tb) =>
|
||||
{
|
||||
List<string> texts = new List<string>();
|
||||
List<LocalizedString> texts = new List<LocalizedString>();
|
||||
selectedDataMultiple.Clear();
|
||||
selectedIndexMultiple.Clear();
|
||||
int i = 0;
|
||||
@@ -276,7 +279,7 @@ namespace Barotrauma
|
||||
}
|
||||
i++;
|
||||
}
|
||||
button.Text = string.Join(", ", texts);
|
||||
button.Text = LocalizedString.Join(", ", texts);
|
||||
// TODO: The callback is called at least twice, remove this?
|
||||
OnSelected?.Invoke(tb.Parent, tb.Parent.UserData);
|
||||
return true;
|
||||
@@ -311,13 +314,12 @@ namespace Barotrauma
|
||||
foreach (GUIComponent child in ListBox.Content.Children)
|
||||
{
|
||||
var tickBox = child.GetChild<GUITickBox>();
|
||||
if (obj == child.UserData) { tickBox.Selected = true; }
|
||||
if (Equals(obj, child.UserData)) { tickBox.Selected = true; }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GUITextBlock textBlock = component as GUITextBlock;
|
||||
if (textBlock == null)
|
||||
if (!(component is GUITextBlock textBlock))
|
||||
{
|
||||
textBlock = component.GetChild<GUITextBlock>();
|
||||
if (textBlock is null && !AllowNonText) { return false; }
|
||||
@@ -368,8 +370,9 @@ namespace Barotrauma
|
||||
Dropped = !Dropped;
|
||||
if (Dropped && Enabled)
|
||||
{
|
||||
OnDropped?.Invoke(this, userData);
|
||||
OnDropped?.Invoke(this, UserData);
|
||||
listBox.UpdateScrollBarSize();
|
||||
listBox.UpdateDimensions();
|
||||
|
||||
GUI.KeyboardDispatcher.Subscriber = this;
|
||||
}
|
||||
|
||||
@@ -177,6 +177,7 @@ namespace Barotrauma
|
||||
spriteBatch.Begin(blendState: BlendState, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
|
||||
}
|
||||
|
||||
var style = Style;
|
||||
if (style != null)
|
||||
{
|
||||
foreach (UISprite uiSprite in style.Sprites[State])
|
||||
@@ -193,7 +194,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (sprite?.Texture != null)
|
||||
else if (sprite?.Texture is { IsDisposed: false })
|
||||
{
|
||||
spriteBatch.Draw(sprite.Texture, Rect.Center.ToVector2(), sourceRect, currentColor * (currentColor.A / 255.0f), Rotation, origin,
|
||||
Scale, SpriteEffects, 0.0f);
|
||||
|
||||
@@ -92,29 +92,19 @@ namespace Barotrauma
|
||||
foreach (RectTransform child in RectTransform.Children)
|
||||
{
|
||||
if (child.GUIComponent.IgnoreLayoutGroups) { continue; }
|
||||
if (child.ScaleBasis == ScaleBasis.BothHeight) { child.MinSize = new Point(child.Rect.Height, child.MinSize.Y); }
|
||||
if (child.ScaleBasis == ScaleBasis.BothWidth) { child.MinSize = new Point(child.MinSize.X, child.Rect.Width); }
|
||||
if (child.ScaleBasis == ScaleBasis.Smallest)
|
||||
|
||||
switch (child.ScaleBasis)
|
||||
{
|
||||
if (Rect.Width < Rect.Height)
|
||||
{
|
||||
child.MinSize = new Point(child.MinSize.X, child.Rect.Width);
|
||||
}
|
||||
else
|
||||
{
|
||||
child.MinSize = new Point(child.Rect.Height, child.MinSize.Y);
|
||||
}
|
||||
}
|
||||
if (child.ScaleBasis == ScaleBasis.Largest)
|
||||
{
|
||||
if (Rect.Width > Rect.Height)
|
||||
{
|
||||
child.MinSize = new Point(child.MinSize.X, child.Rect.Width);
|
||||
}
|
||||
else
|
||||
{
|
||||
child.MinSize = new Point(child.Rect.Height, child.MinSize.Y);
|
||||
}
|
||||
case ScaleBasis.BothHeight:
|
||||
case ScaleBasis.Smallest when Rect.Height <= Rect.Width:
|
||||
case ScaleBasis.Largest when Rect.Height > Rect.Width:
|
||||
child.MinSize = new Point((int)((child.Rect.Height * child.RelativeSize.X) / child.RelativeSize.Y), child.MinSize.Y);
|
||||
break;
|
||||
case ScaleBasis.BothWidth:
|
||||
case ScaleBasis.Smallest when Rect.Width <= Rect.Height:
|
||||
case ScaleBasis.Largest when Rect.Width > Rect.Height:
|
||||
child.MinSize = new Point(child.MinSize.X, (int)((child.Rect.Width * child.RelativeSize.Y) / child.RelativeSize.X));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,42 +134,65 @@ namespace Barotrauma
|
||||
foreach (var child in RectTransform.Children)
|
||||
{
|
||||
if (child.GUIComponent.IgnoreLayoutGroups) { continue; }
|
||||
|
||||
float currentStretchFactor = child.ScaleBasis == ScaleBasis.Normal ? stretchFactor : 1.0f;
|
||||
child.SetPosition(childAnchor);
|
||||
|
||||
void advancePositionsAndCalculateChildSizes(
|
||||
ref int childNonScaledSize,
|
||||
ref float childRelativeSize,
|
||||
int childMinSize,
|
||||
int childMaxSize,
|
||||
int childRectSize,
|
||||
int selfRectSize)
|
||||
{
|
||||
if (child.IsFixedSize)
|
||||
{
|
||||
absPos += childNonScaledSize + absoluteSpacing;
|
||||
}
|
||||
else
|
||||
{
|
||||
absPos += (int)Math.Round(MathHelper.Clamp(childRectSize * currentStretchFactor, childMinSize, childMaxSize) + (absoluteSpacing * currentStretchFactor));
|
||||
if (stretch)
|
||||
{
|
||||
float relativeSize =
|
||||
MathF.Round(childRelativeSize * currentStretchFactor * selfRectSize) / selfRectSize;
|
||||
childRelativeSize = relativeSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Point childNonScaledSize = child.NonScaledSize;
|
||||
Vector2 childRelativeSize = child.RelativeSize;
|
||||
if (isHorizontal)
|
||||
{
|
||||
child.RelativeOffset = new Vector2(relPos, child.RelativeOffset.Y);
|
||||
child.AbsoluteOffset = new Point(absPos, child.AbsoluteOffset.Y);
|
||||
if (child.IsFixedSize)
|
||||
{
|
||||
absPos += child.NonScaledSize.X + absoluteSpacing;
|
||||
}
|
||||
else
|
||||
{
|
||||
absPos += (int)(MathHelper.Clamp(child.Rect.Width * stretchFactor, child.MinSize.X, child.MaxSize.X) + (absoluteSpacing * stretchFactor));
|
||||
if (stretch)
|
||||
{
|
||||
child.RelativeSize = new Vector2(child.RelativeSize.X * stretchFactor, child.RelativeSize.Y);
|
||||
}
|
||||
}
|
||||
advancePositionsAndCalculateChildSizes(
|
||||
ref childNonScaledSize.X,
|
||||
ref childRelativeSize.X,
|
||||
child.MinSize.X,
|
||||
child.MaxSize.X,
|
||||
child.Rect.Width,
|
||||
Rect.Width);
|
||||
}
|
||||
else
|
||||
{
|
||||
child.RelativeOffset = new Vector2(child.RelativeOffset.X, relPos);
|
||||
child.AbsoluteOffset = new Point(child.AbsoluteOffset.X, absPos);
|
||||
if (child.IsFixedSize)
|
||||
{
|
||||
absPos += child.NonScaledSize.Y + absoluteSpacing;
|
||||
}
|
||||
else
|
||||
{
|
||||
absPos += (int)(MathHelper.Clamp(child.Rect.Height * stretchFactor, child.MinSize.Y, child.MaxSize.Y) + (absoluteSpacing * stretchFactor));
|
||||
if (stretch)
|
||||
{
|
||||
child.RelativeSize = new Vector2(child.RelativeSize.X, child.RelativeSize.Y * stretchFactor);
|
||||
}
|
||||
}
|
||||
advancePositionsAndCalculateChildSizes(
|
||||
ref childNonScaledSize.Y,
|
||||
ref childRelativeSize.Y,
|
||||
child.MinSize.Y,
|
||||
child.MaxSize.Y,
|
||||
child.Rect.Height,
|
||||
Rect.Height);
|
||||
}
|
||||
child.NonScaledSize = childNonScaledSize;
|
||||
child.RelativeSize = childRelativeSize;
|
||||
relPos += relativeSpacing * stretchFactor;
|
||||
if (isHorizontal) { relPos = MathF.Round(relPos * Rect.Width) / Rect.Width; }
|
||||
else { relPos = MathF.Round(relPos * Rect.Height) / Rect.Height; }
|
||||
}
|
||||
needsToRecalculate = false;
|
||||
}
|
||||
|
||||
@@ -148,7 +148,11 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
// TODO: fix implicit hiding
|
||||
public bool Selected { get; set; }
|
||||
public override bool Selected
|
||||
{
|
||||
get { return isSelected; }
|
||||
set { isSelected = value; }
|
||||
}
|
||||
|
||||
public IReadOnlyList<GUIComponent> AllSelected => selected;
|
||||
|
||||
@@ -328,7 +332,7 @@ namespace Barotrauma
|
||||
};
|
||||
if (style != null)
|
||||
{
|
||||
GUI.Style.Apply(ContentBackground, "", this);
|
||||
GUIStyle.Apply(ContentBackground, "", this);
|
||||
}
|
||||
if (color.HasValue)
|
||||
{
|
||||
@@ -398,8 +402,7 @@ namespace Barotrauma
|
||||
int i = 0;
|
||||
foreach (GUIComponent child in children)
|
||||
{
|
||||
if ((child.UserData != null && child.UserData.Equals(userData)) ||
|
||||
(child.UserData == null && userData == null))
|
||||
if (Equals(child.UserData, userData))
|
||||
{
|
||||
Select(i, force, autoScroll);
|
||||
if (!SelectMultiple) { return; }
|
||||
@@ -435,7 +438,7 @@ namespace Barotrauma
|
||||
Vector2 topOffset = CalculateTopOffset();
|
||||
int x = (int)topOffset.X;
|
||||
int y = (int)topOffset.Y;
|
||||
|
||||
|
||||
for (int i = 0; i < Content.CountChildren; i++)
|
||||
{
|
||||
GUIComponent child = Content.GetChild(i);
|
||||
@@ -509,23 +512,36 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scrolls the list to the specific element, currently only works when smooth scrolling and PadBottom are enabled.
|
||||
/// Scrolls the list to the specific element.
|
||||
/// </summary>
|
||||
/// <param name="component"></param>
|
||||
public void ScrollToElement(GUIComponent component)
|
||||
public void ScrollToElement(GUIComponent component, bool playSound = true)
|
||||
{
|
||||
SoundPlayer.PlayUISound(GUISoundType.Click);
|
||||
if (playSound) { SoundPlayer.PlayUISound(GUISoundType.Click); }
|
||||
List<GUIComponent> children = Content.Children.ToList();
|
||||
int index = children.IndexOf(component);
|
||||
if (index < 0) { return; }
|
||||
|
||||
void performScroll(GUIComponent c)
|
||||
{
|
||||
if (SmoothScroll && PadBottom)
|
||||
{
|
||||
scrollToElement = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
float diff = isHorizontal ? c.Rect.X - Content.Rect.X : c.Rect.Y - Content.Rect.Y;
|
||||
ScrollBar.BarScroll += diff / TotalSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Content.Children.Contains(component) || !component.Visible)
|
||||
{
|
||||
scrollToElement = null;
|
||||
performScroll(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
scrollToElement = component;
|
||||
performScroll(component);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1215,6 +1231,20 @@ namespace Barotrauma
|
||||
i++;
|
||||
}
|
||||
|
||||
if (isDraggingElement && CurrentDragMode == DragMode.DragOutsideBox && HideDraggedElement)
|
||||
{
|
||||
Rectangle drawRect = DraggedElement.Rect;
|
||||
int draggedElementIndex = Content.GetChildIndex(DraggedElement);
|
||||
CalculateChildrenOffsets((index, point) =>
|
||||
{
|
||||
if (draggedElementIndex == index)
|
||||
{
|
||||
drawRect.Location = Content.Rect.Location + point;
|
||||
}
|
||||
});
|
||||
GUI.DrawRectangle(spriteBatch, drawRect, Color.White * 0.5f, thickness: 2f);
|
||||
}
|
||||
|
||||
if (HideChildrenOutsideFrame)
|
||||
{
|
||||
spriteBatch.End();
|
||||
|
||||
@@ -10,7 +10,8 @@ namespace Barotrauma
|
||||
{
|
||||
public class GUIMessageBox : GUIFrame
|
||||
{
|
||||
public static List<GUIComponent> MessageBoxes = new List<GUIComponent>();
|
||||
#warning TODO: change this to List<GUIMessageBox> and fix incorrect uses of this list
|
||||
public readonly static List<GUIComponent> MessageBoxes = new List<GUIComponent>();
|
||||
private static int DefaultWidth
|
||||
{
|
||||
get { return Math.Max(400, (int)(400 * (GameMain.GraphicsWidth / GUI.ReferenceResolution.X))); }
|
||||
@@ -70,14 +71,14 @@ namespace Barotrauma
|
||||
|
||||
public static GUIComponent VisibleBox => MessageBoxes.LastOrDefault();
|
||||
|
||||
public GUIMessageBox(string headerText, string text, Vector2? relativeSize = null, Point? minSize = null)
|
||||
: this(headerText, text, new string[] { "OK" }, relativeSize, minSize)
|
||||
public GUIMessageBox(LocalizedString headerText, LocalizedString text, Vector2? relativeSize = null, Point? minSize = null)
|
||||
: this(headerText, text, new LocalizedString[] { "OK" }, relativeSize, minSize)
|
||||
{
|
||||
this.Buttons[0].OnClicked = Close;
|
||||
}
|
||||
|
||||
public GUIMessageBox(string headerText, string text, string[] buttons, Vector2? relativeSize = null, Point? minSize = null, Alignment textAlignment = Alignment.TopLeft, Type type = Type.Default, string tag = "", Sprite icon = null, string iconStyle = "", Sprite backgroundIcon = null, bool parseRichText = false)
|
||||
: base(new RectTransform(GUI.Canvas.RelativeSize, GUI.Canvas, Anchor.Center), style: GUI.Style.GetComponentStyle("GUIMessageBox." + type) != null ? "GUIMessageBox." + type : "GUIMessageBox")
|
||||
public GUIMessageBox(RichString headerText, RichString text, LocalizedString[] buttons, Vector2? relativeSize = null, Point? minSize = null, Alignment textAlignment = Alignment.TopLeft, Type type = Type.Default, string tag = "", Sprite icon = null, string iconStyle = "", Sprite backgroundIcon = null)
|
||||
: base(new RectTransform(GUI.Canvas.RelativeSize, GUI.Canvas, Anchor.Center), style: GUIStyle.GetComponentStyle("GUIMessageBox." + type) != null ? "GUIMessageBox." + type : "GUIMessageBox")
|
||||
{
|
||||
int width = (int)(DefaultWidth * type switch
|
||||
{
|
||||
@@ -125,23 +126,24 @@ namespace Barotrauma
|
||||
InnerFrame.RectTransform.ScreenSpaceOffset = new Point(-offset, offset);
|
||||
CanBeFocused = false;
|
||||
}
|
||||
GUI.Style.Apply(InnerFrame, "", this);
|
||||
GUIStyle.Apply(InnerFrame, "", this);
|
||||
this.type = type;
|
||||
Tag = tag;
|
||||
|
||||
#warning TODO: These should be broken into separate methods at least
|
||||
if (type == Type.Default || type == Type.Vote)
|
||||
{
|
||||
Content = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.85f), InnerFrame.RectTransform, Anchor.Center)) { AbsoluteSpacing = 5 };
|
||||
|
||||
Header = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform),
|
||||
headerText, font: GUI.SubHeadingFont, textAlignment: Alignment.Center, wrap: true, parseRichText: parseRichText);
|
||||
GUI.Style.Apply(Header, "", this);
|
||||
headerText, font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Center, wrap: true);
|
||||
GUIStyle.Apply(Header, "", this);
|
||||
Header.RectTransform.MinSize = new Point(0, Header.Rect.Height);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(text))
|
||||
if (!text.IsNullOrWhiteSpace())
|
||||
{
|
||||
Text = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), text, textAlignment: textAlignment, wrap: true, parseRichText: parseRichText);
|
||||
GUI.Style.Apply(Text, "", this);
|
||||
Text = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), text, textAlignment: textAlignment, wrap: true);
|
||||
GUIStyle.Apply(Text, "", this);
|
||||
Text.RectTransform.NonScaledSize = Text.RectTransform.MinSize = Text.RectTransform.MaxSize =
|
||||
new Point(Text.Rect.Width, Text.Rect.Height);
|
||||
Text.RectTransform.IsFixedSize = true;
|
||||
@@ -154,7 +156,7 @@ namespace Barotrauma
|
||||
};
|
||||
|
||||
int buttonSize = 35;
|
||||
var buttonStyle = GUI.Style.GetComponentStyle("GUIButton");
|
||||
var buttonStyle = GUIStyle.GetComponentStyle("GUIButton");
|
||||
if (buttonStyle != null && buttonStyle.Height.HasValue)
|
||||
{
|
||||
buttonSize = buttonStyle.Height.Value;
|
||||
@@ -189,7 +191,7 @@ namespace Barotrauma
|
||||
InnerFrame.RectTransform.AbsoluteOffset = new Point(0, GameMain.GraphicsHeight);
|
||||
CanBeFocused = false;
|
||||
AutoClose = true;
|
||||
GUI.Style.Apply(InnerFrame, "", this);
|
||||
GUIStyle.Apply(InnerFrame, "", this);
|
||||
|
||||
var horizontalLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 0.95f), InnerFrame.RectTransform, Anchor.Center),
|
||||
isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||
@@ -219,11 +221,11 @@ namespace Barotrauma
|
||||
};
|
||||
|
||||
InputType? closeInput = null;
|
||||
if (GameMain.Config.KeyBind(InputType.Use).MouseButton == MouseButton.None)
|
||||
if (GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Use].MouseButton == MouseButton.None)
|
||||
{
|
||||
closeInput = InputType.Use;
|
||||
}
|
||||
else if (GameMain.Config.KeyBind(InputType.Select).MouseButton == MouseButton.None)
|
||||
else if (GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Select].MouseButton == MouseButton.None)
|
||||
{
|
||||
closeInput = InputType.Select;
|
||||
}
|
||||
@@ -236,24 +238,24 @@ namespace Barotrauma
|
||||
{
|
||||
GUIButton btn = component as GUIButton;
|
||||
btn?.OnClicked(btn, btn.UserData);
|
||||
btn?.Flash(GUI.Style.Green);
|
||||
btn?.Flash(GUIStyle.Green);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Header = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), headerText, wrap: true, parseRichText: parseRichText);
|
||||
GUI.Style.Apply(Header, "", this);
|
||||
Header = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), headerText, wrap: true);
|
||||
GUIStyle.Apply(Header, "", this);
|
||||
Header.RectTransform.MinSize = new Point(0, Header.Rect.Height);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(text))
|
||||
if (!text.IsNullOrWhiteSpace())
|
||||
{
|
||||
Text = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), text, textAlignment: textAlignment, wrap: true, parseRichText: parseRichText);
|
||||
GUI.Style.Apply(Text, "", this);
|
||||
Text = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), text, textAlignment: textAlignment, wrap: true);
|
||||
GUIStyle.Apply(Text, "", this);
|
||||
Content.Recalculate();
|
||||
Text.RectTransform.NonScaledSize = Text.RectTransform.MinSize = Text.RectTransform.MaxSize =
|
||||
new Point(Text.Rect.Width, Text.Rect.Height);
|
||||
Text.RectTransform.IsFixedSize = true;
|
||||
if (string.IsNullOrWhiteSpace(headerText))
|
||||
if (headerText.IsNullOrWhiteSpace())
|
||||
{
|
||||
Content.ChildAnchor = Anchor.Center;
|
||||
}
|
||||
@@ -275,7 +277,7 @@ namespace Barotrauma
|
||||
else if (type == Type.Hint)
|
||||
{
|
||||
CanBeFocused = false;
|
||||
GUI.Style.Apply(InnerFrame, "", this);
|
||||
GUIStyle.Apply(InnerFrame, "", this);
|
||||
|
||||
Point absoluteSpacing = GUIStyle.ItemFrameMargin.Multiply(1.0f / 5.0f);
|
||||
var verticalLayoutGroup = new GUILayoutGroup(new RectTransform(GetVerticalLayoutGroupSize(), parent: InnerFrame.RectTransform, anchor: Anchor.Center), childAnchor: Anchor.TopCenter)
|
||||
@@ -353,18 +355,18 @@ namespace Barotrauma
|
||||
};
|
||||
|
||||
Header = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), headerText, wrap: true);
|
||||
GUI.Style.Apply(Header, "", this);
|
||||
GUIStyle.Apply(Header, "", this);
|
||||
Header.RectTransform.MinSize = new Point(0, Header.Rect.Height);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(text))
|
||||
if (!text.IsNullOrWhiteSpace())
|
||||
{
|
||||
Text = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), text, textAlignment: textAlignment, wrap: true);
|
||||
GUI.Style.Apply(Text, "", this);
|
||||
GUIStyle.Apply(Text, "", this);
|
||||
Content.Recalculate();
|
||||
Text.RectTransform.NonScaledSize = Text.RectTransform.MinSize = Text.RectTransform.MaxSize =
|
||||
new Point(Text.Rect.Width, Text.Rect.Height);
|
||||
Text.RectTransform.IsFixedSize = true;
|
||||
if (string.IsNullOrWhiteSpace(headerText))
|
||||
if (headerText.IsNullOrWhiteSpace())
|
||||
{
|
||||
Header.RectTransform.Parent = null;
|
||||
Content.ChildAnchor = Anchor.Center;
|
||||
@@ -410,7 +412,7 @@ namespace Barotrauma
|
||||
/// <summary>
|
||||
/// Use to create a message box of Hint type
|
||||
/// </summary>
|
||||
public GUIMessageBox(string hintIdentifier, string text, Sprite icon) : this("", text, new string[0], textAlignment: Alignment.CenterLeft, type: Type.Hint, icon: icon)
|
||||
public GUIMessageBox(Identifier hintIdentifier, LocalizedString text, Sprite icon) : this("", text, Array.Empty<LocalizedString>(), textAlignment: Alignment.CenterLeft, type: Type.Hint, icon: icon)
|
||||
{
|
||||
if (InnerFrame.FindChild("dontshowagain", recursive: true) is GUITickBox dontShowAgainTickBox)
|
||||
{
|
||||
|
||||
@@ -12,9 +12,12 @@ namespace Barotrauma
|
||||
Int, Float
|
||||
}
|
||||
|
||||
public delegate void OnValueEnteredHandler(GUINumberInput numberInput);
|
||||
public OnValueEnteredHandler OnValueEntered;
|
||||
|
||||
public delegate void OnValueChangedHandler(GUINumberInput numberInput);
|
||||
public OnValueChangedHandler OnValueChanged;
|
||||
|
||||
|
||||
public GUITextBox TextBox { get; private set; }
|
||||
|
||||
public GUIButton PlusButton { get; private set; }
|
||||
@@ -162,7 +165,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public override ScalableFont Font
|
||||
public override GUIFont Font
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -209,6 +212,8 @@ namespace Barotrauma
|
||||
{
|
||||
ClampFloatValue();
|
||||
}
|
||||
|
||||
OnValueEntered?.Invoke(this);
|
||||
};
|
||||
TextBox.OnEnterPressed += (textBox, text) =>
|
||||
{
|
||||
@@ -220,12 +225,14 @@ namespace Barotrauma
|
||||
{
|
||||
ClampFloatValue();
|
||||
}
|
||||
|
||||
OnValueEntered?.Invoke(this);
|
||||
return true;
|
||||
};
|
||||
|
||||
var buttonArea = new GUIFrame(new RectTransform(new Vector2(_relativeButtonAreaWidth, 1.0f), LayoutGroup.RectTransform, Anchor.CenterRight), style: null);
|
||||
PlusButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.5f), buttonArea.RectTransform), style: null);
|
||||
GUI.Style.Apply(PlusButton, "PlusButton", this);
|
||||
GUIStyle.Apply(PlusButton, "PlusButton", this);
|
||||
PlusButton.OnButtonDown += () =>
|
||||
{
|
||||
pressedTimer = pressedDelay;
|
||||
@@ -246,7 +253,7 @@ namespace Barotrauma
|
||||
};
|
||||
|
||||
MinusButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.5f), buttonArea.RectTransform, Anchor.BottomRight), style: null);
|
||||
GUI.Style.Apply(MinusButton, "MinusButton", this);
|
||||
GUIStyle.Apply(MinusButton, "MinusButton", this);
|
||||
MinusButton.OnButtonDown += () =>
|
||||
{
|
||||
pressedTimer = pressedDelay;
|
||||
|
||||
395
Barotrauma/BarotraumaClient/ClientSource/GUI/GUIPrefab.cs
Normal file
395
Barotrauma/BarotraumaClient/ClientSource/GUI/GUIPrefab.cs
Normal file
@@ -0,0 +1,395 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public abstract class GUIPrefab : Prefab
|
||||
{
|
||||
public GUIPrefab(ContentXElement element, UIStyleFile file) : base(file, element) { }
|
||||
|
||||
protected override Identifier DetermineIdentifier(XElement element)
|
||||
{
|
||||
return element.NameAsIdentifier();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class GUISelector<T> where T : GUIPrefab
|
||||
{
|
||||
public readonly PrefabSelector<T> Prefabs = new PrefabSelector<T>();
|
||||
public readonly Identifier Identifier;
|
||||
|
||||
public GUISelector(string identifier)
|
||||
{
|
||||
Identifier = identifier.ToIdentifier();
|
||||
}
|
||||
}
|
||||
|
||||
public class GUIFontPrefab : GUIPrefab
|
||||
{
|
||||
private readonly ContentXElement element;
|
||||
private ScalableFont font;
|
||||
public ScalableFont Font
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Language != GameSettings.CurrentConfig.Language) { LoadFont(); }
|
||||
return font;
|
||||
}
|
||||
}
|
||||
|
||||
private ScalableFont cjkFont;
|
||||
|
||||
public ScalableFont CjkFont
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Language != GameSettings.CurrentConfig.Language) { LoadFont(); }
|
||||
if (font.IsCJK) { return font; }
|
||||
return cjkFont;
|
||||
}
|
||||
}
|
||||
|
||||
public LanguageIdentifier Language { get; private set; }
|
||||
|
||||
public GUIFontPrefab(ContentXElement element, UIStyleFile file) : base(element, file)
|
||||
{
|
||||
this.element = element;
|
||||
LoadFont();
|
||||
}
|
||||
|
||||
public void LoadFont()
|
||||
{
|
||||
string fontPath = GetFontFilePath(element);
|
||||
uint size = GetFontSize(element);
|
||||
bool dynamicLoading = GetFontDynamicLoading(element);
|
||||
bool isCJK = GetIsCJK(element);
|
||||
font?.Dispose();
|
||||
cjkFont?.Dispose();
|
||||
font = new ScalableFont(fontPath, size, GameMain.Instance.GraphicsDevice, dynamicLoading, isCJK)
|
||||
{
|
||||
ForceUpperCase = element.GetAttributeBool("forceuppercase", false)
|
||||
};
|
||||
if (!isCJK)
|
||||
{
|
||||
cjkFont = ExtractCjkFont(element)
|
||||
?? new ScalableFont("Content/Fonts/NotoSans/NotoSansCJKsc-Bold.otf",
|
||||
font.Size, GameMain.Instance.GraphicsDevice, dynamicLoading: true, isCJK: true);
|
||||
cjkFont.ForceUpperCase = font.ForceUpperCase;
|
||||
}
|
||||
Language = GameSettings.CurrentConfig.Language;
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
font?.Dispose(); font = null;
|
||||
cjkFont?.Dispose(); cjkFont = null;
|
||||
}
|
||||
|
||||
private ScalableFont ExtractCjkFont(ContentXElement element)
|
||||
{
|
||||
foreach (var subElement in element.Elements().Reverse())
|
||||
{
|
||||
if (subElement.NameAsIdentifier() != "override") { continue; }
|
||||
|
||||
if (subElement.GetAttributeBool("iscjk", false))
|
||||
{
|
||||
return new ScalableFont(subElement, GameMain.Instance.GraphicsDevice);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private string GetFontFilePath(ContentXElement element)
|
||||
{
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
if (!subElement.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||
if (GameSettings.CurrentConfig.Language == subElement.GetAttributeIdentifier("language", "").ToLanguageIdentifier())
|
||||
{
|
||||
return subElement.GetAttributeContentPath("file")?.Value;
|
||||
}
|
||||
}
|
||||
return element.GetAttributeContentPath("file")?.Value;
|
||||
}
|
||||
|
||||
private uint GetFontSize(XElement element, uint defaultSize = 14)
|
||||
{
|
||||
//check if any of the language override fonts want to override the font size as well
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
if (!subElement.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||
if (GameSettings.CurrentConfig.Language == subElement.GetAttributeIdentifier("language", "").ToLanguageIdentifier())
|
||||
{
|
||||
uint overrideFontSize = GetFontSize(subElement, 0);
|
||||
if (overrideFontSize > 0) { return (uint)Math.Round(overrideFontSize * GameSettings.CurrentConfig.Graphics.TextScale); }
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
if (!subElement.Name.ToString().Equals("size", StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||
Point maxResolution = subElement.GetAttributePoint("maxresolution", new Point(int.MaxValue, int.MaxValue));
|
||||
if (GameMain.GraphicsWidth <= maxResolution.X && GameMain.GraphicsHeight <= maxResolution.Y)
|
||||
{
|
||||
return (uint)Math.Round(subElement.GetAttributeInt("size", 14) * GameSettings.CurrentConfig.Graphics.TextScale);
|
||||
}
|
||||
}
|
||||
return (uint)Math.Round(defaultSize * GameSettings.CurrentConfig.Graphics.TextScale);
|
||||
}
|
||||
|
||||
private bool GetFontDynamicLoading(XElement element)
|
||||
{
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
if (!subElement.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||
if (GameSettings.CurrentConfig.Language == subElement.GetAttributeIdentifier("language", "").ToLanguageIdentifier())
|
||||
{
|
||||
return subElement.GetAttributeBool("dynamicloading", false);
|
||||
}
|
||||
}
|
||||
return element.GetAttributeBool("dynamicloading", false);
|
||||
}
|
||||
|
||||
private bool GetIsCJK(XElement element)
|
||||
{
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
if (!subElement.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||
if (GameSettings.CurrentConfig.Language == subElement.GetAttributeIdentifier("language", "").ToLanguageIdentifier())
|
||||
{
|
||||
return subElement.GetAttributeBool("iscjk", false);
|
||||
}
|
||||
}
|
||||
return element.GetAttributeBool("iscjk", false);
|
||||
}
|
||||
}
|
||||
|
||||
public class GUIFont : GUISelector<GUIFontPrefab>
|
||||
{
|
||||
public GUIFont(string identifier) : base(identifier) { }
|
||||
|
||||
public bool HasValue => Prefabs.Any();
|
||||
|
||||
public ScalableFont Value => Prefabs.ActivePrefab.Font;
|
||||
|
||||
public static implicit operator ScalableFont(GUIFont reference) => reference.Value;
|
||||
|
||||
public bool ForceUpperCase => HasValue && Value.ForceUpperCase;
|
||||
|
||||
public uint Size => HasValue ? Value.Size : 0;
|
||||
|
||||
private ScalableFont GetFontForStr(LocalizedString str) => GetFontForStr(str.Value);
|
||||
|
||||
private ScalableFont GetFontForStr(string str) =>
|
||||
TextManager.IsCJK(str) ? Prefabs.ActivePrefab.CjkFont : Prefabs.ActivePrefab.Font;
|
||||
|
||||
public void DrawString(SpriteBatch sb, LocalizedString text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects se, float layerDepth)
|
||||
{
|
||||
DrawString(sb, text.Value, position, color, rotation, origin, scale, se, layerDepth);
|
||||
}
|
||||
|
||||
public void DrawString(SpriteBatch sb, string text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects se, float layerDepth)
|
||||
{
|
||||
GetFontForStr(text).DrawString(sb, text, position, color, rotation, origin, scale, se, layerDepth);
|
||||
}
|
||||
|
||||
public void DrawString(SpriteBatch sb, LocalizedString text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects se, float layerDepth, Alignment alignment = Alignment.TopLeft)
|
||||
{
|
||||
DrawString(sb, text.Value, position, color, rotation, origin, scale, se, layerDepth, alignment);
|
||||
}
|
||||
|
||||
public void DrawString(SpriteBatch sb, string text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects se, float layerDepth, Alignment alignment = Alignment.TopLeft, ForceUpperCase forceUpperCase = Barotrauma.ForceUpperCase.Inherit)
|
||||
{
|
||||
GetFontForStr(text).DrawString(sb, text, position, color, rotation, origin, scale, se, layerDepth, alignment, forceUpperCase);
|
||||
}
|
||||
|
||||
public void DrawString(SpriteBatch sb, LocalizedString text, Vector2 position, Color color, ForceUpperCase forceUpperCase = Barotrauma.ForceUpperCase.Inherit, bool italics = false)
|
||||
{
|
||||
DrawString(sb, text.Value, position, color, forceUpperCase, italics);
|
||||
}
|
||||
|
||||
public void DrawString(SpriteBatch sb, string text, Vector2 position, Color color, ForceUpperCase forceUpperCase = Barotrauma.ForceUpperCase.Inherit, bool italics = false)
|
||||
{
|
||||
GetFontForStr(text).DrawString(sb, text, position, color, forceUpperCase, italics);
|
||||
}
|
||||
|
||||
public void DrawStringWithColors(SpriteBatch sb, string text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects se, float layerDepth, in ImmutableArray<RichTextData>? richTextData, int rtdOffset = 0, Alignment alignment = Alignment.TopLeft, ForceUpperCase forceUpperCase = Barotrauma.ForceUpperCase.Inherit)
|
||||
{
|
||||
GetFontForStr(text).DrawStringWithColors(sb, text, position, color, rotation, origin, scale, se, layerDepth, richTextData, rtdOffset, alignment, forceUpperCase);
|
||||
}
|
||||
|
||||
public Vector2 MeasureString(LocalizedString str, bool removeExtraSpacing = false)
|
||||
{
|
||||
return GetFontForStr(str).MeasureString(str, removeExtraSpacing);
|
||||
}
|
||||
|
||||
public Vector2 MeasureChar(char c)
|
||||
{
|
||||
return GetFontForStr($"{c}").MeasureChar(c);
|
||||
}
|
||||
|
||||
public string WrapText(string text, float width)
|
||||
=> GetFontForStr(text).WrapText(text, width);
|
||||
|
||||
public string WrapText(string text, float width, int requestCharPos, out Vector2 requestedCharPos)
|
||||
=> GetFontForStr(text).WrapText(text, width, requestCharPos, out requestedCharPos);
|
||||
|
||||
public string WrapText(string text, float width, out Vector2[] allCharPositions)
|
||||
=> GetFontForStr(text).WrapText(text, width, out allCharPositions);
|
||||
|
||||
public float LineHeight => Value.LineHeight;
|
||||
}
|
||||
|
||||
public class GUIColorPrefab : GUIPrefab
|
||||
{
|
||||
public readonly Color Color;
|
||||
|
||||
public GUIColorPrefab(ContentXElement element, UIStyleFile file) : base(element, file)
|
||||
{
|
||||
Color = element.GetAttributeColor("color", Color.White);
|
||||
}
|
||||
|
||||
public override void Dispose() { }
|
||||
}
|
||||
|
||||
public class GUIColor : GUISelector<GUIColorPrefab>
|
||||
{
|
||||
public GUIColor(string identifier) : base(identifier) { }
|
||||
|
||||
public Color Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return Prefabs.ActivePrefab.Color;
|
||||
}
|
||||
}
|
||||
|
||||
public static implicit operator Color(GUIColor reference) => reference.Value;
|
||||
|
||||
public static Color operator*(GUIColor value, float scale)
|
||||
{
|
||||
return value.Value * scale;
|
||||
}
|
||||
}
|
||||
|
||||
public class GUISpritePrefab : GUIPrefab
|
||||
{
|
||||
public readonly UISprite Sprite;
|
||||
|
||||
public GUISpritePrefab(ContentXElement element, UIStyleFile file) : base(element, file)
|
||||
{
|
||||
Sprite = new UISprite(element);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
Sprite.Sprite.Remove();
|
||||
}
|
||||
}
|
||||
|
||||
public class GUISprite : GUISelector<GUISpritePrefab>
|
||||
{
|
||||
public GUISprite(string identifier) : base(identifier) { }
|
||||
|
||||
public UISprite Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return Prefabs.ActivePrefab.Sprite;
|
||||
}
|
||||
}
|
||||
|
||||
public static implicit operator UISprite(GUISprite reference) => reference.Value;
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, Rectangle rect, Color color, SpriteEffects spriteEffects = SpriteEffects.None)
|
||||
{
|
||||
Value.Draw(spriteBatch, rect, color, spriteEffects);
|
||||
}
|
||||
}
|
||||
|
||||
public class GUISpriteSheetPrefab : GUIPrefab
|
||||
{
|
||||
public readonly SpriteSheet SpriteSheet;
|
||||
|
||||
public GUISpriteSheetPrefab(ContentXElement element, UIStyleFile file) : base(element, file)
|
||||
{
|
||||
SpriteSheet = new SpriteSheet(element);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
SpriteSheet.Remove();
|
||||
}
|
||||
}
|
||||
|
||||
public class GUISpriteSheet : GUISelector<GUISpriteSheetPrefab>
|
||||
{
|
||||
public GUISpriteSheet(string identifier) : base(identifier) { }
|
||||
|
||||
public SpriteSheet Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return Prefabs.ActivePrefab.SpriteSheet;
|
||||
}
|
||||
}
|
||||
|
||||
public int FrameCount => Value.FrameCount;
|
||||
public Point FrameSize => Value.FrameSize;
|
||||
|
||||
public void Draw(ISpriteBatch spriteBatch, Vector2 pos, float rotate = 0, float scale = 1, SpriteEffects spriteEffects = SpriteEffects.None)
|
||||
{
|
||||
Value.Draw(spriteBatch, pos, rotate, scale, spriteEffects);
|
||||
}
|
||||
|
||||
public void Draw(ISpriteBatch spriteBatch, Vector2 pos, Color color, Vector2 origin, float rotate = 0, float scale = 1, SpriteEffects spriteEffects = SpriteEffects.None, float? depth = null)
|
||||
{
|
||||
Value.Draw(spriteBatch, pos, color, origin, rotate, scale, spriteEffects, depth);
|
||||
}
|
||||
|
||||
public void Draw(ISpriteBatch spriteBatch, int spriteIndex, Vector2 pos, Color color, Vector2 origin, float rotate, Vector2 scale, SpriteEffects spriteEffects = SpriteEffects.None, float? depth = null)
|
||||
{
|
||||
Value.Draw(spriteBatch, spriteIndex, pos, color, origin, rotate, scale, spriteEffects, depth);
|
||||
}
|
||||
|
||||
public static implicit operator SpriteSheet(GUISpriteSheet reference) => reference.Value;
|
||||
}
|
||||
|
||||
public class GUICursorPrefab : GUIPrefab
|
||||
{
|
||||
public readonly Sprite[] Sprites;
|
||||
|
||||
public GUICursorPrefab(ContentXElement element, UIStyleFile file) : base(element, file)
|
||||
{
|
||||
Sprites = new Sprite[Enum.GetValues(typeof(CursorState)).Length];
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
CursorState state = subElement.GetAttributeEnum("state", CursorState.Default);
|
||||
Sprites[(int)state] = new Sprite(subElement);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
foreach (var sprite in Sprites)
|
||||
{
|
||||
sprite?.Remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class GUICursor : GUISelector<GUICursorPrefab>
|
||||
{
|
||||
public GUICursor(string identifier) : base(identifier) { }
|
||||
|
||||
public Sprite this[CursorState k] => Prefabs.ActivePrefab.Sprites[(int)k];
|
||||
}
|
||||
}
|
||||
@@ -47,9 +47,9 @@ namespace Barotrauma
|
||||
}
|
||||
isHorizontal = (Rect.Width > Rect.Height);
|
||||
frame = new GUIFrame(new RectTransform(Vector2.One, rectT));
|
||||
GUI.Style.Apply(frame, "", this);
|
||||
GUIStyle.Apply(frame, "", this);
|
||||
slider = new GUIFrame(new RectTransform(Vector2.One, rectT));
|
||||
GUI.Style.Apply(slider, "Slider", this);
|
||||
GUIStyle.Apply(slider, "Slider", this);
|
||||
this.showFrame = showFrame;
|
||||
this.barSize = barSize;
|
||||
Enabled = true;
|
||||
@@ -62,10 +62,10 @@ namespace Barotrauma
|
||||
public Rectangle GetSliderRect(float fillAmount)
|
||||
{
|
||||
Rectangle sliderArea = new Rectangle(
|
||||
frame.Rect.X + (int)style.Padding.X,
|
||||
frame.Rect.Y + (int)style.Padding.Y,
|
||||
(int)(frame.Rect.Width - style.Padding.X - style.Padding.Z),
|
||||
(int)(frame.Rect.Height - style.Padding.Y - style.Padding.W));
|
||||
frame.Rect.X + (int)Style.Padding.X,
|
||||
frame.Rect.Y + (int)Style.Padding.Y,
|
||||
(int)(frame.Rect.Width - Style.Padding.X - Style.Padding.Z),
|
||||
(int)(frame.Rect.Height - Style.Padding.Y - Style.Padding.W));
|
||||
|
||||
Vector4 sliceBorderSizes = Vector4.Zero;
|
||||
if (slider.sprites.ContainsKey(slider.State) && (slider.sprites[slider.State].First()?.Slice ?? false))
|
||||
@@ -116,10 +116,10 @@ namespace Barotrauma
|
||||
|
||||
var sliderRect = GetSliderRect(barSize);
|
||||
|
||||
slider.RectTransform.AbsoluteOffset = new Point((int)style.Padding.X, (int)style.Padding.Y);
|
||||
slider.RectTransform.AbsoluteOffset = new Point((int)Style.Padding.X, (int)Style.Padding.Y);
|
||||
slider.RectTransform.MaxSize = new Point(
|
||||
(int)(Rect.Width - style.Padding.X + style.Padding.Z),
|
||||
(int)(Rect.Height - style.Padding.Y + style.Padding.W));
|
||||
(int)(Rect.Width - Style.Padding.X + Style.Padding.Z),
|
||||
(int)(Rect.Height - Style.Padding.Y + Style.Padding.W));
|
||||
frame.Visible = showFrame;
|
||||
slider.Visible = BarSize > 0.0f;
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Barotrauma.Extensions;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
|
||||
namespace Barotrauma
|
||||
@@ -29,7 +28,7 @@ namespace Barotrauma
|
||||
|
||||
public bool IsBooleanSwitch;
|
||||
|
||||
public override string ToolTip
|
||||
public override RichString ToolTip
|
||||
{
|
||||
get { return base.ToolTip; }
|
||||
set
|
||||
@@ -203,7 +202,7 @@ namespace Barotrauma
|
||||
CanBeFocused = true;
|
||||
this.isHorizontal = isHorizontal ?? (Rect.Width > Rect.Height);
|
||||
Frame = new GUIFrame(new RectTransform(Vector2.One, rectT));
|
||||
GUI.Style.Apply(Frame, IsHorizontal ? "GUIFrameHorizontal" : "GUIFrameVertical", this);
|
||||
GUIStyle.Apply(Frame, IsHorizontal ? "GUIFrameHorizontal" : "GUIFrameVertical", this);
|
||||
this.barSize = barSize;
|
||||
|
||||
Bar = new GUIButton(new RectTransform(Vector2.One, rectT, IsHorizontal ? Anchor.CenterLeft : Anchor.TopCenter), color: color, style: null);
|
||||
@@ -224,7 +223,7 @@ namespace Barotrauma
|
||||
break;
|
||||
}
|
||||
|
||||
GUI.Style.Apply(Bar, IsHorizontal ? "GUIButtonHorizontal" : "GUIButtonVertical", this);
|
||||
GUIStyle.Apply(Bar, IsHorizontal ? "GUIButtonHorizontal" : "GUIButtonVertical", this);
|
||||
Bar.OnPressed = SelectBar;
|
||||
enabled = true;
|
||||
UpdateRect();
|
||||
@@ -313,6 +312,7 @@ namespace Barotrauma
|
||||
MoveButton(new Vector2(
|
||||
Math.Sign(PlayerInput.MousePosition.X - Bar.Rect.Center.X) * Bar.Rect.Width * barScale,
|
||||
Math.Sign(PlayerInput.MousePosition.Y - Bar.Rect.Center.Y) * Bar.Rect.Height * barScale));
|
||||
OnReleased?.Invoke(this, BarScroll);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,523 +1,202 @@
|
||||
using Barotrauma.Extensions;
|
||||
using System;
|
||||
using Barotrauma.Extensions;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class GUIStyle
|
||||
public static class GUIStyle
|
||||
{
|
||||
private Dictionary<string, GUIComponentStyle> componentStyles;
|
||||
|
||||
private readonly XElement configElement;
|
||||
|
||||
private GraphicsDevice graphicsDevice;
|
||||
|
||||
private ScalableFont defaultFont;
|
||||
|
||||
public ScalableFont Font { get; private set; }
|
||||
public ScalableFont GlobalFont { get; private set; }
|
||||
public ScalableFont UnscaledSmallFont { get; private set; }
|
||||
public ScalableFont SmallFont { get; private set; }
|
||||
public ScalableFont LargeFont { get; private set; }
|
||||
public ScalableFont SubHeadingFont { get; private set; }
|
||||
public ScalableFont DigitalFont { get; private set; }
|
||||
public ScalableFont HotkeyFont { get; private set; }
|
||||
public ScalableFont MonospacedFont { get; private set; }
|
||||
|
||||
public Dictionary<ScalableFont, bool> ForceFontUpperCase
|
||||
public readonly static ImmutableDictionary<Identifier, GUIFont> Fonts;
|
||||
public readonly static ImmutableDictionary<Identifier, GUISprite> Sprites;
|
||||
public readonly static ImmutableDictionary<Identifier, GUISpriteSheet> SpriteSheets;
|
||||
public readonly static ImmutableDictionary<Identifier, GUIColor> Colors;
|
||||
static GUIStyle()
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
} = new Dictionary<ScalableFont, bool>();
|
||||
var guiClassProperties = typeof(GUIStyle).GetFields(BindingFlags.Public | BindingFlags.Static);
|
||||
|
||||
public readonly Sprite[] CursorSprite = new Sprite[7];
|
||||
ImmutableDictionary<Identifier, T> getPropertiesOfType<T>() where T : class
|
||||
{
|
||||
return guiClassProperties
|
||||
.Where(p => p.FieldType == typeof(T))
|
||||
.Select(p => (p.Name.ToIdentifier(), p.GetValue(null) as T))
|
||||
.ToImmutableDictionary();
|
||||
}
|
||||
|
||||
public UISprite RadiationSprite { get; private set; }
|
||||
public SpriteSheet RadiationAnimSpriteSheet { get; private set; }
|
||||
Fonts = getPropertiesOfType<GUIFont>();
|
||||
Sprites = getPropertiesOfType<GUISprite>();
|
||||
SpriteSheets = getPropertiesOfType<GUISpriteSheet>();
|
||||
Colors = getPropertiesOfType<GUIColor>();
|
||||
}
|
||||
|
||||
public SpriteSheet SavingIndicator { get; private set; }
|
||||
public readonly static PrefabCollection<GUIComponentStyle> ComponentStyles = new PrefabCollection<GUIComponentStyle>();
|
||||
|
||||
public UISprite UIGlow { get; private set; }
|
||||
public readonly static GUIFont Font = new GUIFont("Font");
|
||||
public readonly static GUIFont GlobalFont = new GUIFont("GlobalFont");
|
||||
public readonly static GUIFont UnscaledSmallFont = new GUIFont("UnscaledSmallFont");
|
||||
public readonly static GUIFont SmallFont = new GUIFont("SmallFont");
|
||||
public readonly static GUIFont LargeFont = new GUIFont("LargeFont");
|
||||
public readonly static GUIFont SubHeadingFont = new GUIFont("SubHeadingFont");
|
||||
public readonly static GUIFont DigitalFont = new GUIFont("DigitalFont");
|
||||
public readonly static GUIFont HotkeyFont = new GUIFont("HotkeyFont");
|
||||
public readonly static GUIFont MonospacedFont = new GUIFont("MonospacedFont");
|
||||
|
||||
public UISprite PingCircle { get; private set; }
|
||||
public readonly static GUICursor CursorSprite = new GUICursor("Cursor");
|
||||
|
||||
public UISprite YouAreHereCircle { get; private set; }
|
||||
public readonly static GUISprite SubmarineLocationIcon = new GUISprite("SubmarineLocationIcon");
|
||||
public readonly static GUISprite Arrow = new GUISprite("Arrow");
|
||||
public readonly static GUISprite SpeechBubbleIcon = new GUISprite("SpeechBubbleIcon");
|
||||
public readonly static GUISprite BrokenIcon = new GUISprite("BrokenIcon");
|
||||
public readonly static GUISprite YouAreHereCircle = new GUISprite("YouAreHereCircle");
|
||||
|
||||
public UISprite UIGlowCircular { get; private set; }
|
||||
public readonly static GUISprite Radiation = new GUISprite("Radiation");
|
||||
public readonly static GUISpriteSheet RadiationAnimSpriteSheet = new GUISpriteSheet("RadiationAnimSpriteSheet");
|
||||
|
||||
public UISprite UIGlowSolidCircular { get; private set; }
|
||||
public UISprite UIThermalGlow { get; private set; }
|
||||
public readonly static GUISpriteSheet SavingIndicator = new GUISpriteSheet("SavingIndicator");
|
||||
public readonly static GUISpriteSheet GenericThrobber = new GUISpriteSheet("GenericThrobber");
|
||||
|
||||
public UISprite ButtonPulse { get; private set; }
|
||||
public readonly static GUISprite UIGlow = new GUISprite("UIGlow");
|
||||
public readonly static GUISprite TalentGlow = new GUISprite("TalentGlow");
|
||||
public readonly static GUISprite PingCircle = new GUISprite("PingCircle");
|
||||
public readonly static GUISprite UIGlowCircular = new GUISprite("UIGlowCircular");
|
||||
public readonly static GUISprite UIGlowSolidCircular = new GUISprite("UIGlowSolidCircular");
|
||||
public readonly static GUISprite UIThermalGlow = new GUISprite("UIGlowSolidCircular");
|
||||
public readonly static GUISprite ButtonPulse = new GUISprite("ButtonPulse");
|
||||
public readonly static GUISprite WalletPortraitBG = new GUISprite("WalletPortraitBG");
|
||||
public readonly static GUISprite CrewWalletIconSmall = new GUISprite("CrewWalletIconSmall");
|
||||
|
||||
public SpriteSheet FocusIndicator { get; private set; }
|
||||
public readonly static GUISprite EndRoundButtonPulse = new GUISprite("EndRoundButtonPulse");
|
||||
|
||||
public UISprite IconOverflowIndicator { get; private set; }
|
||||
public readonly static GUISpriteSheet FocusIndicator = new GUISpriteSheet("FocusIndicator");
|
||||
|
||||
public readonly static GUISprite IconOverflowIndicator = new GUISprite("IconOverflowIndicator");
|
||||
|
||||
/// <summary>
|
||||
/// General green color used for elements whose colors are set from code
|
||||
/// </summary>
|
||||
public Color Green { get; private set; } = Color.LightGreen;
|
||||
public readonly static GUIColor Green = new GUIColor("Green");
|
||||
|
||||
/// <summary>
|
||||
/// General red color used for elements whose colors are set from code
|
||||
/// </summary>
|
||||
public Color Orange { get; private set; } = Color.Orange;
|
||||
public readonly static GUIColor Orange = new GUIColor("Orange");
|
||||
|
||||
/// <summary>
|
||||
/// General red color used for elements whose colors are set from code
|
||||
/// </summary>
|
||||
public Color Red { get; private set; } = Color.Red;
|
||||
public readonly static GUIColor Red = new GUIColor("Red");
|
||||
|
||||
/// <summary>
|
||||
/// General blue color used for elements whose colors are set from code
|
||||
/// </summary>
|
||||
public Color Blue { get; private set; } = Color.Blue;
|
||||
public readonly static GUIColor Blue = new GUIColor("Blue");
|
||||
|
||||
/// <summary>
|
||||
/// General yellow color used for elements whose colors are set from code
|
||||
/// </summary>
|
||||
public Color Yellow { get; private set; } = Color.Yellow;
|
||||
public readonly static GUIColor Yellow = new GUIColor("Yellow");
|
||||
|
||||
public Color ColorInventoryEmpty { get; private set; } = Color.Red;
|
||||
public Color ColorInventoryHalf { get; private set; } = Color.Orange;
|
||||
public Color ColorInventoryFull { get; private set; } = Color.LightGreen;
|
||||
public Color ColorInventoryBackground { get; private set; } = Color.Gray;
|
||||
public Color ColorInventoryEmptyOverlay { get; private set; } = Color.Red;
|
||||
/// <summary>
|
||||
/// Color to display the name of modded servers in the server list.
|
||||
/// </summary>
|
||||
public readonly static GUIColor ModdedServerColor = new GUIColor("ModdedServerColor");
|
||||
|
||||
public Color TextColor { get; private set; } = Color.White * 0.8f;
|
||||
public Color TextColorBright { get; private set; } = Color.White * 0.9f;
|
||||
public Color TextColorDark { get; private set; } = Color.Black * 0.9f;
|
||||
public Color TextColorDim { get; private set; } = Color.White * 0.6f;
|
||||
public readonly static GUIColor ColorInventoryEmpty = new GUIColor("ColorInventoryEmpty");
|
||||
public readonly static GUIColor ColorInventoryHalf = new GUIColor("ColorInventoryHalf");
|
||||
public readonly static GUIColor ColorInventoryFull = new GUIColor("ColorInventoryFull");
|
||||
public readonly static GUIColor ColorInventoryBackground = new GUIColor("ColorInventoryBackground");
|
||||
public readonly static GUIColor ColorInventoryEmptyOverlay = new GUIColor("ColorInventoryEmptyOverlay");
|
||||
|
||||
public Color ItemQualityColorPoor { get; private set; } = Color.DarkRed;
|
||||
public Color ItemQualityColorNormal { get; private set; } = Color.Gray;
|
||||
public Color ItemQualityColorGood { get; private set; } = Color.LightGreen;
|
||||
public Color ItemQualityColorExcellent { get; private set; } = Color.LightBlue;
|
||||
public Color ItemQualityColorMasterwork { get; private set; } = Color.MediumPurple;
|
||||
public readonly static GUIColor TextColorNormal = new GUIColor("TextColorNormal");
|
||||
public readonly static GUIColor TextColorBright = new GUIColor("TextColorBright");
|
||||
public readonly static GUIColor TextColorDark = new GUIColor("TextColorDark");
|
||||
public readonly static GUIColor TextColorDim = new GUIColor("TextColorDim");
|
||||
|
||||
public Color ColorReputationVeryLow { get; private set; } = Color.Red;
|
||||
public Color ColorReputationLow { get; private set; } = Color.Orange;
|
||||
public Color ColorReputationNeutral { get; private set; } = Color.White * 0.8f;
|
||||
public Color ColorReputationHigh { get; private set; } = Color.LightBlue;
|
||||
public Color ColorReputationVeryHigh { get; private set; } = Color.Blue;
|
||||
public readonly static GUIColor ItemQualityColorPoor = new GUIColor("ItemQualityColorPoor");
|
||||
public readonly static GUIColor ItemQualityColorNormal = new GUIColor("ItemQualityColorNormal");
|
||||
public readonly static GUIColor ItemQualityColorGood = new GUIColor("ItemQualityColorGood");
|
||||
public readonly static GUIColor ItemQualityColorExcellent = new GUIColor("ItemQualityColorExcellent");
|
||||
public readonly static GUIColor ItemQualityColorMasterwork = new GUIColor("ItemQualityColorMasterwork");
|
||||
|
||||
public readonly static GUIColor ColorReputationVeryLow = new GUIColor("ColorReputationVeryLow");
|
||||
public readonly static GUIColor ColorReputationLow = new GUIColor("ColorReputationLow");
|
||||
public readonly static GUIColor ColorReputationNeutral = new GUIColor("ColorReputationNeutral");
|
||||
public readonly static GUIColor ColorReputationHigh = new GUIColor("ColorReputationHigh");
|
||||
public readonly static GUIColor ColorReputationVeryHigh = new GUIColor("ColorReputationVeryHigh");
|
||||
|
||||
// Inventory
|
||||
public Color EquipmentSlotIconColor { get; private set; } = new Color(99, 70, 64);
|
||||
public readonly static GUIColor EquipmentSlotIconColor = new GUIColor("EquipmentSlotIconColor");
|
||||
|
||||
// Health HUD
|
||||
public Color BuffColorLow { get; private set; } = Color.LightGreen;
|
||||
public Color BuffColorMedium { get; private set; } = Color.Green;
|
||||
public Color BuffColorHigh { get; private set; } = Color.DarkGreen;
|
||||
public readonly static GUIColor BuffColorLow = new GUIColor("BuffColorLow");
|
||||
public readonly static GUIColor BuffColorMedium = new GUIColor("BuffColorMedium");
|
||||
public readonly static GUIColor BuffColorHigh = new GUIColor("BuffColorHigh");
|
||||
|
||||
public Color DebuffColorLow { get; private set; } = Color.DarkSalmon;
|
||||
public Color DebuffColorMedium { get; private set; } = Color.Red;
|
||||
public Color DebuffColorHigh { get; private set; } = Color.DarkRed;
|
||||
public readonly static GUIColor DebuffColorLow = new GUIColor("DebuffColorLow");
|
||||
public readonly static GUIColor DebuffColorMedium = new GUIColor("DebuffColorMedium");
|
||||
public readonly static GUIColor DebuffColorHigh = new GUIColor("DebuffColorHigh");
|
||||
|
||||
public Color HealthBarColorLow { get; private set; } = Color.Red;
|
||||
public Color HealthBarColorMedium { get; private set; } = Color.Orange;
|
||||
public Color HealthBarColorHigh { get; private set; } = new Color(78, 114, 88);
|
||||
public readonly static GUIColor HealthBarColorLow = new GUIColor("HealthBarColorLow");
|
||||
public readonly static GUIColor HealthBarColorMedium = new GUIColor("HealthBarColorMedium");
|
||||
public readonly static GUIColor HealthBarColorHigh = new GUIColor("HealthBarColorHigh");
|
||||
|
||||
public Color EquipmentIndicatorNotEquipped { get; private set; } = Color.Gray;
|
||||
public Color EquipmentIndicatorEquipped { get; private set; } = new Color(105, 202, 125);
|
||||
public Color EquipmentIndicatorRunningOut { get; private set; } = new Color(202, 105, 105);
|
||||
public readonly static GUIColor EquipmentIndicatorNotEquipped = new GUIColor("EquipmentIndicatorNotEquipped");
|
||||
public readonly static GUIColor EquipmentIndicatorEquipped = new GUIColor("EquipmentIndicatorEquipped");
|
||||
public readonly static GUIColor EquipmentIndicatorRunningOut = new GUIColor("EquipmentIndicatorRunningOut");
|
||||
|
||||
public static Point ItemFrameMargin => new Point(50, 56).Multiply(GUI.SlicedSpriteScale);
|
||||
public static Point ItemFrameOffset => new Point(0, 3).Multiply(GUI.SlicedSpriteScale);
|
||||
|
||||
public GUIStyle(XElement element, GraphicsDevice graphicsDevice)
|
||||
public static GUIComponentStyle GetComponentStyle(string name)
|
||||
=> ComponentStyles.ContainsKey(name) ? ComponentStyles[name] : null;
|
||||
|
||||
public static void Apply(GUIComponent targetComponent, string styleName = "", GUIComponent parent = null)
|
||||
{
|
||||
this.graphicsDevice = graphicsDevice;
|
||||
componentStyles = new Dictionary<string, GUIComponentStyle>();
|
||||
configElement = element;
|
||||
foreach (XElement subElement in configElement.Elements())
|
||||
{
|
||||
var name = subElement.Name.ToString().ToLowerInvariant();
|
||||
switch (name)
|
||||
{
|
||||
case "cursor":
|
||||
if (subElement.HasElements)
|
||||
{
|
||||
foreach (var children in subElement.Descendants())
|
||||
{
|
||||
var index = children.GetAttributeInt("state", (int)CursorState.Default);
|
||||
CursorSprite[index] = new Sprite(children);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CursorSprite[(int)CursorState.Default] = new Sprite(subElement);
|
||||
}
|
||||
break;
|
||||
case "green":
|
||||
Green = subElement.GetAttributeColor("color", Green);
|
||||
break;
|
||||
case "orange":
|
||||
Orange = subElement.GetAttributeColor("color", Orange);
|
||||
break;
|
||||
case "red":
|
||||
Red = subElement.GetAttributeColor("color", Red);
|
||||
break;
|
||||
case "blue":
|
||||
Blue = subElement.GetAttributeColor("color", Blue);
|
||||
break;
|
||||
case "yellow":
|
||||
Yellow = subElement.GetAttributeColor("color", Yellow);
|
||||
break;
|
||||
case "colorinventoryempty":
|
||||
ColorInventoryEmpty = subElement.GetAttributeColor("color", ColorInventoryEmpty);
|
||||
break;
|
||||
case "colorinventoryhalf":
|
||||
ColorInventoryHalf = subElement.GetAttributeColor("color", ColorInventoryHalf);
|
||||
break;
|
||||
case "colorinventoryfull":
|
||||
ColorInventoryFull = subElement.GetAttributeColor("color", ColorInventoryFull);
|
||||
break;
|
||||
case "colorinventorybackground":
|
||||
ColorInventoryBackground = subElement.GetAttributeColor("color", ColorInventoryBackground);
|
||||
break;
|
||||
case "colorinventoryemptyoverlay":
|
||||
ColorInventoryEmptyOverlay = subElement.GetAttributeColor("color", ColorInventoryEmptyOverlay);
|
||||
break;
|
||||
case "textcolordark":
|
||||
TextColorDark = subElement.GetAttributeColor("color", TextColorDark);
|
||||
break;
|
||||
case "textcolorbright":
|
||||
TextColorBright = subElement.GetAttributeColor("color", TextColorBright);
|
||||
break;
|
||||
case "textcolordim":
|
||||
TextColorDim = subElement.GetAttributeColor("color", TextColorDim);
|
||||
break;
|
||||
case "textcolornormal":
|
||||
case "textcolor":
|
||||
TextColor = subElement.GetAttributeColor("color", TextColor);
|
||||
break;
|
||||
case "colorreputationverylow":
|
||||
ColorReputationVeryLow = subElement.GetAttributeColor("color", TextColor);
|
||||
break;
|
||||
case "colorreputationlow":
|
||||
ColorReputationLow = subElement.GetAttributeColor("color", TextColor);
|
||||
break;
|
||||
case "colorreputationneutral":
|
||||
ColorReputationNeutral = subElement.GetAttributeColor("color", TextColor);
|
||||
break;
|
||||
case "colorreputationhigh":
|
||||
ColorReputationHigh = subElement.GetAttributeColor("color", TextColor);
|
||||
break;
|
||||
case "colorreputationveryhigh":
|
||||
ColorReputationVeryHigh = subElement.GetAttributeColor("color", TextColor);
|
||||
break;
|
||||
case "equipmentsloticoncolor":
|
||||
EquipmentSlotIconColor = subElement.GetAttributeColor("color", EquipmentSlotIconColor);
|
||||
break;
|
||||
case "buffcolorlow":
|
||||
BuffColorLow = subElement.GetAttributeColor("color", BuffColorLow);
|
||||
break;
|
||||
case "buffcolormedium":
|
||||
BuffColorMedium = subElement.GetAttributeColor("color", BuffColorMedium);
|
||||
break;
|
||||
case "buffcolorhigh":
|
||||
BuffColorHigh = subElement.GetAttributeColor("color", BuffColorHigh);
|
||||
break;
|
||||
case "debuffcolorlow":
|
||||
DebuffColorLow = subElement.GetAttributeColor("color", DebuffColorLow);
|
||||
break;
|
||||
case "debuffcolormedium":
|
||||
DebuffColorMedium = subElement.GetAttributeColor("color", DebuffColorMedium);
|
||||
break;
|
||||
case "debuffcolorhigh":
|
||||
DebuffColorHigh = subElement.GetAttributeColor("color", DebuffColorHigh);
|
||||
break;
|
||||
case "healthbarcolorlow":
|
||||
HealthBarColorLow = subElement.GetAttributeColor("color", HealthBarColorLow);
|
||||
break;
|
||||
case "healthbarcolormedium":
|
||||
HealthBarColorMedium = subElement.GetAttributeColor("color", HealthBarColorMedium);
|
||||
break;
|
||||
case "healthbarcolorhigh":
|
||||
HealthBarColorHigh = subElement.GetAttributeColor("color", HealthBarColorHigh);
|
||||
break;
|
||||
case "equipmentindicatornotequipped":
|
||||
EquipmentIndicatorNotEquipped = subElement.GetAttributeColor("color", EquipmentIndicatorNotEquipped);
|
||||
break;
|
||||
case "equipmentindicatorequipped":
|
||||
EquipmentIndicatorEquipped = subElement.GetAttributeColor("color", EquipmentIndicatorEquipped);
|
||||
break;
|
||||
case "equipmentindicatorrunningout":
|
||||
EquipmentIndicatorRunningOut = subElement.GetAttributeColor("color", EquipmentIndicatorRunningOut);
|
||||
break;
|
||||
case "uiglow":
|
||||
UIGlow = new UISprite(subElement);
|
||||
break;
|
||||
case "pingcircle":
|
||||
PingCircle = new UISprite(subElement);
|
||||
break;
|
||||
case "youareherecircle":
|
||||
YouAreHereCircle = new UISprite(subElement);
|
||||
break;
|
||||
case "radiation":
|
||||
RadiationSprite = new UISprite(subElement);
|
||||
break;
|
||||
case "radiationanimspritesheet":
|
||||
RadiationAnimSpriteSheet = new SpriteSheet(subElement);
|
||||
break;
|
||||
case "uiglowcircular":
|
||||
UIGlowCircular = new UISprite(subElement);
|
||||
break;
|
||||
case "uiglowsolidcircular":
|
||||
UIGlowSolidCircular = new UISprite(subElement);
|
||||
break;
|
||||
case "uithermalglow":
|
||||
UIThermalGlow = new UISprite(subElement);
|
||||
break;
|
||||
case "endroundbuttonpulse":
|
||||
ButtonPulse = new UISprite(subElement);
|
||||
break;
|
||||
case "iconoverflowindicator":
|
||||
IconOverflowIndicator = new UISprite(subElement);
|
||||
break;
|
||||
case "focusindicator":
|
||||
FocusIndicator = new SpriteSheet(subElement);
|
||||
break;
|
||||
case "savingindicator":
|
||||
SavingIndicator = new SpriteSheet(subElement);
|
||||
break;
|
||||
case "font":
|
||||
Font = LoadFont(subElement, graphicsDevice);
|
||||
ForceFontUpperCase[Font] = subElement.GetAttributeBool("forceuppercase", false);
|
||||
break;
|
||||
case "globalfont":
|
||||
GlobalFont = LoadFont(subElement, graphicsDevice);
|
||||
ForceFontUpperCase[GlobalFont] = subElement.GetAttributeBool("forceuppercase", false);
|
||||
break;
|
||||
case "unscaledsmallfont":
|
||||
UnscaledSmallFont = LoadFont(subElement, graphicsDevice);
|
||||
ForceFontUpperCase[UnscaledSmallFont] = subElement.GetAttributeBool("forceuppercase", false);
|
||||
break;
|
||||
case "smallfont":
|
||||
SmallFont = LoadFont(subElement, graphicsDevice);
|
||||
ForceFontUpperCase[SmallFont] = subElement.GetAttributeBool("forceuppercase", false);
|
||||
break;
|
||||
case "largefont":
|
||||
LargeFont = LoadFont(subElement, graphicsDevice);
|
||||
ForceFontUpperCase[LargeFont] = subElement.GetAttributeBool("forceuppercase", false);
|
||||
break;
|
||||
case "digitalfont":
|
||||
DigitalFont = LoadFont(subElement, graphicsDevice);
|
||||
ForceFontUpperCase[DigitalFont] = subElement.GetAttributeBool("forceuppercase", false);
|
||||
break;
|
||||
case "monospacedfont":
|
||||
MonospacedFont = LoadFont(subElement, graphicsDevice);
|
||||
ForceFontUpperCase[MonospacedFont] = subElement.GetAttributeBool("forceuppercase", false);
|
||||
break;
|
||||
case "hotkeyfont":
|
||||
HotkeyFont = LoadFont(subElement, graphicsDevice);
|
||||
ForceFontUpperCase[HotkeyFont] = subElement.GetAttributeBool("forceuppercase", false);
|
||||
break;
|
||||
case "objectivetitle":
|
||||
case "subheading":
|
||||
SubHeadingFont = LoadFont(subElement, graphicsDevice);
|
||||
ForceFontUpperCase[SubHeadingFont] = subElement.GetAttributeBool("forceuppercase", false);
|
||||
break;
|
||||
default:
|
||||
GUIComponentStyle componentStyle = new GUIComponentStyle(subElement, this);
|
||||
componentStyles.Add(subElement.Name.ToString().ToLowerInvariant(), componentStyle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (GlobalFont == null)
|
||||
{
|
||||
GlobalFont = Font;
|
||||
DebugConsole.NewMessage("Global font not defined in the current UI style file. The global font is used to render western symbols when using Chinese/Japanese/Korean localization. Using default font instead...", Color.Orange);
|
||||
}
|
||||
|
||||
// TODO: Needs to unregister if we ever remove GUIStyles.
|
||||
GameMain.Instance.ResolutionChanged += RescaleElements;
|
||||
Apply(targetComponent, styleName.ToIdentifier(), parent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the default font of the currently selected language
|
||||
/// </summary>
|
||||
public ScalableFont LoadCurrentDefaultFont()
|
||||
{
|
||||
defaultFont?.Dispose();
|
||||
defaultFont = null;
|
||||
foreach (XElement subElement in configElement.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "font":
|
||||
defaultFont = LoadFont(subElement, graphicsDevice);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return defaultFont;
|
||||
}
|
||||
|
||||
|
||||
private void RescaleElements()
|
||||
{
|
||||
if (configElement == null) { return; }
|
||||
if (configElement.Elements() == null) { return; }
|
||||
foreach (XElement subElement in configElement.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "font":
|
||||
if (Font == null) { continue; }
|
||||
Font.Size = GetFontSize(subElement);
|
||||
break;
|
||||
case "smallfont":
|
||||
if (SmallFont == null) { continue; }
|
||||
SmallFont.Size = GetFontSize(subElement);
|
||||
break;
|
||||
case "largefont":
|
||||
if (LargeFont == null) { continue; }
|
||||
LargeFont.Size = GetFontSize(subElement);
|
||||
break;
|
||||
case "hotkeyfont":
|
||||
if (HotkeyFont == null) { continue; }
|
||||
HotkeyFont.Size = GetFontSize(subElement);
|
||||
break;
|
||||
case "objectivetitle":
|
||||
case "subheading":
|
||||
if (SubHeadingFont == null) { continue; }
|
||||
SubHeadingFont.Size = GetFontSize(subElement);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var componentStyle in componentStyles.Values)
|
||||
{
|
||||
componentStyle.GetSize(componentStyle.Element);
|
||||
foreach (var childStyle in componentStyle.ChildStyles.Values)
|
||||
{
|
||||
childStyle.GetSize(childStyle.Element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ScalableFont LoadFont(XElement element, GraphicsDevice graphicsDevice)
|
||||
{
|
||||
string file = GetFontFilePath(element);
|
||||
uint size = GetFontSize(element);
|
||||
bool dynamicLoading = GetFontDynamicLoading(element);
|
||||
bool isCJK = GetIsCJK(element);
|
||||
return new ScalableFont(file, size, graphicsDevice, dynamicLoading, isCJK);
|
||||
}
|
||||
|
||||
private uint GetFontSize(XElement element, uint defaultSize = 14)
|
||||
{
|
||||
//check if any of the language override fonts want to override the font size as well
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
if (!subElement.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||
if (GameMain.Config.Language.Equals(subElement.GetAttributeString("language", ""), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
uint overrideFontSize = GetFontSize(subElement, 0);
|
||||
if (overrideFontSize > 0) { return (uint)Math.Round(overrideFontSize * GameSettings.TextScale); }
|
||||
}
|
||||
}
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
if (!subElement.Name.ToString().Equals("size", StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||
Point maxResolution = subElement.GetAttributePoint("maxresolution", new Point(int.MaxValue, int.MaxValue));
|
||||
if (GameMain.GraphicsWidth <= maxResolution.X && GameMain.GraphicsHeight <= maxResolution.Y)
|
||||
{
|
||||
return (uint)Math.Round(subElement.GetAttributeInt("size", 14) * GameSettings.TextScale);
|
||||
}
|
||||
}
|
||||
return (uint)Math.Round(defaultSize * GameSettings.TextScale);
|
||||
}
|
||||
|
||||
private string GetFontFilePath(XElement element)
|
||||
{
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
if (!subElement.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||
if (GameMain.Config.Language.Equals(subElement.GetAttributeString("language", ""), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return subElement.GetAttributeString("file", "");
|
||||
}
|
||||
}
|
||||
return element.GetAttributeString("file", "");
|
||||
}
|
||||
|
||||
private bool GetFontDynamicLoading(XElement element)
|
||||
{
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
if (!subElement.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||
if (GameMain.Config.Language.Equals(subElement.GetAttributeString("language", ""), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return subElement.GetAttributeBool("dynamicloading", false);
|
||||
}
|
||||
}
|
||||
return element.GetAttributeBool("dynamicloading", false);
|
||||
}
|
||||
|
||||
private bool GetIsCJK(XElement element)
|
||||
{
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
if (!subElement.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||
if (GameMain.Config.Language.Equals(subElement.GetAttributeString("language", ""), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return subElement.GetAttributeBool("iscjk", false);
|
||||
}
|
||||
}
|
||||
return element.GetAttributeBool("iscjk", false);
|
||||
}
|
||||
|
||||
public GUIComponentStyle GetComponentStyle(string name)
|
||||
{
|
||||
componentStyles.TryGetValue(name.ToLowerInvariant(), out GUIComponentStyle style);
|
||||
return style;
|
||||
}
|
||||
|
||||
public void Apply(GUIComponent targetComponent, string styleName = "", GUIComponent parent = null)
|
||||
public static void Apply(GUIComponent targetComponent, Identifier styleName, GUIComponent parent = null)
|
||||
{
|
||||
GUIComponentStyle componentStyle = null;
|
||||
if (parent != null)
|
||||
{
|
||||
GUIComponentStyle parentStyle = parent.Style;
|
||||
|
||||
if (parent.Style == null)
|
||||
if (parentStyle == null)
|
||||
{
|
||||
string parentStyleName = parent.GetType().Name.ToLowerInvariant();
|
||||
Identifier parentStyleName = parent.GetType().Name.ToIdentifier();
|
||||
|
||||
if (!componentStyles.TryGetValue(parentStyleName, out parentStyle))
|
||||
if (!ComponentStyles.ContainsKey(parentStyleName))
|
||||
{
|
||||
DebugConsole.ThrowError("Couldn't find a GUI style \""+ parentStyleName + "\"");
|
||||
DebugConsole.ThrowError($"Couldn't find a GUI style \"{parentStyleName}\"");
|
||||
return;
|
||||
}
|
||||
parentStyle = ComponentStyles[parentStyleName];
|
||||
}
|
||||
|
||||
string childStyleName = string.IsNullOrEmpty(styleName) ? targetComponent.GetType().Name : styleName;
|
||||
parentStyle.ChildStyles.TryGetValue(childStyleName.ToLowerInvariant(), out componentStyle);
|
||||
Identifier childStyleName = styleName.IsEmpty ? targetComponent.GetType().Name.ToIdentifier() : styleName;
|
||||
parentStyle.ChildStyles.TryGetValue(childStyleName, out componentStyle);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (string.IsNullOrEmpty(styleName))
|
||||
Identifier styleIdentifier = styleName.ToIdentifier();
|
||||
if (styleIdentifier == Identifier.Empty)
|
||||
{
|
||||
styleName = targetComponent.GetType().Name;
|
||||
styleIdentifier = targetComponent.GetType().Name.ToIdentifier();
|
||||
}
|
||||
if (!componentStyles.TryGetValue(styleName.ToLowerInvariant(), out componentStyle))
|
||||
if (!ComponentStyles.ContainsKey(styleIdentifier))
|
||||
{
|
||||
DebugConsole.ThrowError("Couldn't find a GUI style \""+ styleName+"\"");
|
||||
DebugConsole.ThrowError($"Couldn't find a GUI style \"{styleIdentifier}\"");
|
||||
return;
|
||||
}
|
||||
componentStyle = ComponentStyles[styleIdentifier];
|
||||
}
|
||||
|
||||
targetComponent.ApplyStyle(componentStyle);
|
||||
}
|
||||
|
||||
public Color GetQualityColor(int quality)
|
||||
public static GUIColor GetQualityColor(int quality)
|
||||
{
|
||||
switch (quality)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Barotrauma.Extensions;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -7,9 +8,16 @@ using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public enum ForceUpperCase
|
||||
{
|
||||
Inherit,
|
||||
No,
|
||||
Yes
|
||||
}
|
||||
|
||||
public class GUITextBlock : GUIComponent
|
||||
{
|
||||
protected string text;
|
||||
protected RichString text;
|
||||
|
||||
protected Alignment textAlignment;
|
||||
|
||||
@@ -20,10 +28,10 @@ namespace Barotrauma
|
||||
|
||||
protected Color textColor, disabledTextColor, selectedTextColor;
|
||||
|
||||
private string wrappedText;
|
||||
private LocalizedString wrappedText;
|
||||
private string censoredText;
|
||||
|
||||
public delegate string TextGetterHandler();
|
||||
public delegate LocalizedString TextGetterHandler();
|
||||
public TextGetterHandler TextGetter;
|
||||
|
||||
public bool Wrap;
|
||||
@@ -41,8 +49,6 @@ namespace Barotrauma
|
||||
|
||||
private float textDepth;
|
||||
|
||||
private ScalableFont originalFont;
|
||||
|
||||
public Vector2 TextOffset { get; set; }
|
||||
|
||||
private Vector4 padding;
|
||||
@@ -56,7 +62,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public override ScalableFont Font
|
||||
public override GUIFont Font
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -65,23 +71,25 @@ namespace Barotrauma
|
||||
set
|
||||
{
|
||||
if (base.Font == value) { return; }
|
||||
base.Font = originalFont = value;
|
||||
if (text != null && GUI.Style.ForceFontUpperCase.ContainsKey(Font) && GUI.Style.ForceFontUpperCase[Font])
|
||||
{
|
||||
Text = text.ToUpper();
|
||||
}
|
||||
base.Font = value;
|
||||
if (text != null) { Text = text; }
|
||||
SetTextPos();
|
||||
}
|
||||
}
|
||||
|
||||
public string Text
|
||||
public RichString Text
|
||||
{
|
||||
get { return text; }
|
||||
set
|
||||
{
|
||||
string newText = forceUpperCase || (GUI.Style.ForceFontUpperCase.ContainsKey(Font) && GUI.Style.ForceFontUpperCase[Font]) || (style != null && style.ForceUpperCase) ?
|
||||
value?.ToUpper() :
|
||||
value;
|
||||
#warning TODO: Remove this eventually. Nobody should want to pass null.
|
||||
value ??= "";
|
||||
RichString newText = forceUpperCase switch
|
||||
{
|
||||
ForceUpperCase.Inherit => value.CaseTiedToFontAndStyle(Font, Style),
|
||||
ForceUpperCase.No => value.CaseTiedToFontAndStyle(null, null),
|
||||
ForceUpperCase.Yes => value.ToUpper()
|
||||
};
|
||||
|
||||
if (Text == newText) { return; }
|
||||
|
||||
@@ -89,21 +97,12 @@ namespace Barotrauma
|
||||
if (autoScaleHorizontal || autoScaleVertical) { textScale = 1.0f; }
|
||||
|
||||
text = newText;
|
||||
wrappedText = newText;
|
||||
if (TextManager.IsCJK(text))
|
||||
{
|
||||
//switch to fallback CJK font
|
||||
if (!Font.IsCJK) { base.Font = GUI.CJKFont; }
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Font == GUI.CJKFont) { base.Font = originalFont; }
|
||||
}
|
||||
wrappedText = newText.SanitizedString;
|
||||
SetTextPos();
|
||||
}
|
||||
}
|
||||
|
||||
public string WrappedText
|
||||
public LocalizedString WrappedText
|
||||
{
|
||||
get { return wrappedText; }
|
||||
}
|
||||
@@ -117,7 +116,11 @@ namespace Barotrauma
|
||||
public Vector2 TextPos
|
||||
{
|
||||
get { return textPos; }
|
||||
set { textPos = value; }
|
||||
set
|
||||
{
|
||||
textPos = value;
|
||||
ClearCaretPositions();
|
||||
}
|
||||
}
|
||||
|
||||
public float TextScale
|
||||
@@ -169,8 +172,8 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private bool forceUpperCase;
|
||||
public bool ForceUpperCase
|
||||
private ForceUpperCase forceUpperCase = ForceUpperCase.Inherit;
|
||||
public ForceUpperCase ForceUpperCase
|
||||
{
|
||||
get { return forceUpperCase; }
|
||||
set
|
||||
@@ -178,12 +181,7 @@ namespace Barotrauma
|
||||
if (forceUpperCase == value) { return; }
|
||||
|
||||
forceUpperCase = value;
|
||||
if (forceUpperCase ||
|
||||
(style != null && style.ForceUpperCase) ||
|
||||
(GUI.Style.ForceFontUpperCase.ContainsKey(Font) && GUI.Style.ForceFontUpperCase[Font]))
|
||||
{
|
||||
Text = text?.ToUpper();
|
||||
}
|
||||
if (text != null) { Text = text; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,7 +245,7 @@ namespace Barotrauma
|
||||
|
||||
public class StrikethroughSettings
|
||||
{
|
||||
public Color Color { get; set; } = GUI.Style.Red;
|
||||
public Color Color { get; set; } = GUIStyle.Red;
|
||||
private int thickness;
|
||||
private int expand;
|
||||
|
||||
@@ -266,13 +264,9 @@ namespace Barotrauma
|
||||
|
||||
public StrikethroughSettings Strikethrough = null;
|
||||
|
||||
public List<RichTextData> RichTextData
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public ImmutableArray<RichTextData>? RichTextData => text.RichTextData;
|
||||
|
||||
public bool HasColorHighlight => RichTextData != null;
|
||||
public bool HasColorHighlight => RichTextData.HasValue;
|
||||
|
||||
public bool OverrideRichTextDataAlpha = true;
|
||||
|
||||
@@ -292,9 +286,9 @@ namespace Barotrauma
|
||||
/// This is the new constructor.
|
||||
/// If the rectT height is set 0, the height is calculated from the text.
|
||||
/// </summary>
|
||||
public GUITextBlock(RectTransform rectT, string text, Color? textColor = null, ScalableFont font = null,
|
||||
public GUITextBlock(RectTransform rectT, RichString text, Color? textColor = null, GUIFont font = null,
|
||||
Alignment textAlignment = Alignment.Left, bool wrap = false, string style = "", Color? color = null,
|
||||
bool playerInput = false, bool parseRichText = false)
|
||||
bool playerInput = false)
|
||||
: base(style, rectT)
|
||||
{
|
||||
if (color.HasValue)
|
||||
@@ -306,28 +300,15 @@ namespace Barotrauma
|
||||
OverrideTextColor(textColor.Value);
|
||||
}
|
||||
|
||||
if (parseRichText)
|
||||
{
|
||||
RichTextData = Barotrauma.RichTextData.GetRichTextData(text, out text);
|
||||
if (RichTextData != null && RichTextData.Count == 0)
|
||||
{
|
||||
RichTextData = null;
|
||||
}
|
||||
}
|
||||
|
||||
//if the text is in chinese/korean/japanese and we're not using a CJK-compatible font,
|
||||
//use the default CJK font as a fallback
|
||||
var selectedFont = originalFont = font ?? GUI.Font;
|
||||
if (TextManager.IsCJK(text) && !selectedFont.IsCJK)
|
||||
{
|
||||
selectedFont = GUI.CJKFont;
|
||||
}
|
||||
var selectedFont = font ?? GUIStyle.Font;
|
||||
this.Font = selectedFont;
|
||||
this.textAlignment = textAlignment;
|
||||
this.Wrap = wrap;
|
||||
this.Text = text ?? "";
|
||||
this.playerInput = playerInput;
|
||||
if (rectT.Rect.Height == 0 && !string.IsNullOrEmpty(text))
|
||||
if (rectT.Rect.Height == 0 && !text.IsNullOrEmpty())
|
||||
{
|
||||
CalculateHeightFromText();
|
||||
}
|
||||
@@ -339,11 +320,6 @@ namespace Barotrauma
|
||||
Enabled = true;
|
||||
Censor = false;
|
||||
}
|
||||
public GUITextBlock(RectTransform rectT, List<RichTextData> richTextData, string text, Color? textColor = null, ScalableFont font = null, Alignment textAlignment = Alignment.Left, bool wrap = false, string style = "", Color? color = null, bool playerInput = false)
|
||||
: this(rectT, text, textColor, font, textAlignment, wrap, style, color, playerInput)
|
||||
{
|
||||
this.RichTextData = richTextData;
|
||||
}
|
||||
|
||||
public void CalculateHeightFromText(int padding = 0, bool removeExtraSpacing = false)
|
||||
{
|
||||
@@ -351,10 +327,9 @@ namespace Barotrauma
|
||||
RectTransform.Resize(new Point(RectTransform.Rect.Width, (int)Font.MeasureString(wrappedText, removeExtraSpacing).Y + padding));
|
||||
}
|
||||
|
||||
public void SetRichText(string richText)
|
||||
public void SetRichText(LocalizedString richText)
|
||||
{
|
||||
RichTextData = Barotrauma.RichTextData.GetRichTextData(richText, out string sanitizedText);
|
||||
Text = sanitizedText;
|
||||
Text = RichString.Rich(richText);
|
||||
}
|
||||
|
||||
public override void ApplyStyle(GUIComponentStyle componentStyle)
|
||||
@@ -368,41 +343,34 @@ namespace Barotrauma
|
||||
disabledTextColor = componentStyle.DisabledTextColor;
|
||||
selectedTextColor = componentStyle.SelectedTextColor;
|
||||
|
||||
switch (componentStyle.Font)
|
||||
if (Font == null || !componentStyle.Font.IsEmpty)
|
||||
{
|
||||
case "font":
|
||||
Font = componentStyle.Style.Font;
|
||||
break;
|
||||
case "smallfont":
|
||||
Font = componentStyle.Style.SmallFont;
|
||||
break;
|
||||
case "largefont":
|
||||
Font = componentStyle.Style.LargeFont;
|
||||
break;
|
||||
case "objectivetitle":
|
||||
case "subheading":
|
||||
Font = componentStyle.Style.SubHeadingFont;
|
||||
break;
|
||||
Font = GUIStyle.Fonts[componentStyle.Font.AppendIfMissing("Font")];
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearCaretPositions()
|
||||
{
|
||||
cachedCaretPositions = ImmutableArray<Vector2>.Empty;
|
||||
}
|
||||
|
||||
public void SetTextPos()
|
||||
{
|
||||
cachedCaretPositions = ImmutableArray<Vector2>.Empty;
|
||||
ClearCaretPositions();
|
||||
if (text == null) { return; }
|
||||
|
||||
censoredText = string.IsNullOrEmpty(text) ? "" : new string('\u2022', text.Length);
|
||||
censoredText = text.IsNullOrEmpty() ? "" : new string('\u2022', text.Length);
|
||||
|
||||
var rect = Rect;
|
||||
|
||||
overflowClipActive = false;
|
||||
wrappedText = text;
|
||||
wrappedText = text.SanitizedString;
|
||||
|
||||
TextSize = MeasureText(text);
|
||||
TextSize = MeasureText(text.SanitizedString);
|
||||
|
||||
if (Wrap && rect.Width > 0)
|
||||
{
|
||||
wrappedText = ToolBox.WrapText(text, rect.Width - padding.X - padding.Z, Font, textScale);
|
||||
wrappedText = ToolBox.WrapText(text.SanitizedString, rect.Width - padding.X - padding.Z, Font, textScale);
|
||||
TextSize = MeasureText(wrappedText);
|
||||
}
|
||||
else if (OverflowClip)
|
||||
@@ -426,15 +394,15 @@ namespace Barotrauma
|
||||
textPos = new Vector2(padding.X + (rect.Width - padding.Z - padding.X) / 2.0f, padding.Y + (rect.Height - padding.Y - padding.W) / 2.0f);
|
||||
origin = TextSize * 0.5f;
|
||||
|
||||
origin.X = 0;
|
||||
if (textAlignment.HasFlag(Alignment.Left) && !overflowClipActive)
|
||||
{
|
||||
textPos.X = padding.X;
|
||||
origin.X = 0;
|
||||
}
|
||||
if (textAlignment.HasFlag(Alignment.Right) || overflowClipActive)
|
||||
{
|
||||
textPos.X = rect.Width - padding.Z;
|
||||
origin.X = TextSize.X;
|
||||
//origin.X = TextSize.X;
|
||||
}
|
||||
if (textAlignment.HasFlag(Alignment.Top))
|
||||
{
|
||||
@@ -454,7 +422,12 @@ namespace Barotrauma
|
||||
textPos.Y = (int)textPos.Y;
|
||||
}
|
||||
|
||||
private Vector2 MeasureText(string text)
|
||||
private Vector2 MeasureText(LocalizedString text)
|
||||
{
|
||||
return MeasureText(text.Value);
|
||||
}
|
||||
|
||||
private Vector2 MeasureText(string text)
|
||||
{
|
||||
if (Font == null) return Vector2.Zero;
|
||||
|
||||
@@ -498,12 +471,20 @@ namespace Barotrauma
|
||||
{
|
||||
return cachedCaretPositions;
|
||||
}
|
||||
string textDrawn = Censor ? CensoredText : Text;
|
||||
string textDrawn = Censor ? CensoredText : Text.SanitizedValue;
|
||||
float w = Wrap
|
||||
? (Rect.Width - Padding.X - Padding.Z) / TextScale
|
||||
: float.PositiveInfinity;
|
||||
Font.WrapText(textDrawn, w, out Vector2[] positions);
|
||||
cachedCaretPositions = positions.Select(p => p * TextScale + TextPos - Origin * TextScale).ToImmutableArray();
|
||||
string wrapped = Font.WrapText(textDrawn, w, out Vector2[] positions);
|
||||
int textWidth = (int)Font.MeasureString(wrapped).X;
|
||||
int alignmentXDiff
|
||||
= textAlignment.HasFlag(Alignment.Right) ? textWidth
|
||||
: textAlignment.HasFlag(Alignment.Center) ? textWidth / 2
|
||||
: 0;
|
||||
cachedCaretPositions = positions
|
||||
.Select(p => p - new Vector2(alignmentXDiff, 0))
|
||||
.Select(p => p * TextScale + TextPos - Origin * TextScale)
|
||||
.ToImmutableArray();
|
||||
return cachedCaretPositions;
|
||||
}
|
||||
|
||||
@@ -584,7 +565,7 @@ namespace Barotrauma
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(text))
|
||||
if (!text.IsNullOrEmpty())
|
||||
{
|
||||
Vector2 pos = rect.Location.ToVector2() + textPos + TextOffset;
|
||||
if (RoundToNearestPixel)
|
||||
@@ -605,28 +586,29 @@ namespace Barotrauma
|
||||
|
||||
if (!HasColorHighlight)
|
||||
{
|
||||
string textToShow = Censor ? censoredText : (Wrap ? wrappedText : text);
|
||||
string textToShow = Censor ? censoredText : (Wrap ? wrappedText.Value : text.SanitizedValue);
|
||||
Color colorToShow = currentTextColor * (currentTextColor.A / 255.0f);
|
||||
|
||||
if (Shadow)
|
||||
{
|
||||
Vector2 shadowOffset = new Vector2(GUI.IntScale(2));
|
||||
Font.DrawString(spriteBatch, textToShow, pos + shadowOffset, Color.Black, 0.0f, origin, TextScale, SpriteEffects.None, textDepth);
|
||||
Font.DrawString(spriteBatch, textToShow, pos + shadowOffset, Color.Black, 0.0f, origin, TextScale, SpriteEffects.None, textDepth, alignment: textAlignment, forceUpperCase: ForceUpperCase);
|
||||
}
|
||||
|
||||
Font.DrawString(spriteBatch, textToShow, pos, colorToShow, 0.0f, origin, TextScale, SpriteEffects.None, textDepth);
|
||||
Font.DrawString(spriteBatch, textToShow, pos, colorToShow, 0.0f, origin, TextScale, SpriteEffects.None, textDepth, alignment: textAlignment, forceUpperCase: ForceUpperCase);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (OverrideRichTextDataAlpha)
|
||||
{
|
||||
RichTextData.ForEach(rt => rt.Alpha = currentTextColor.A / 255.0f);
|
||||
RichTextData.Value.ForEach(rt => rt.Alpha = currentTextColor.A / 255.0f);
|
||||
}
|
||||
Font.DrawStringWithColors(spriteBatch, Censor ? censoredText : (Wrap ? wrappedText : text), pos,
|
||||
currentTextColor * (currentTextColor.A / 255.0f), 0.0f, origin, TextScale, SpriteEffects.None, textDepth, RichTextData);
|
||||
Font.DrawStringWithColors(spriteBatch, Censor ? censoredText : (Wrap ? wrappedText : text.SanitizedString).Value, pos,
|
||||
currentTextColor * (currentTextColor.A / 255.0f), 0.0f, origin, TextScale, SpriteEffects.None, textDepth, RichTextData.Value, alignment: textAlignment, forceUpperCase: ForceUpperCase);
|
||||
}
|
||||
|
||||
Strikethrough?.Draw(spriteBatch, (int)Math.Ceiling(TextSize.X / 2f), pos.X, ForceUpperCase ? pos.Y : pos.Y + GUI.Scale * 2f);
|
||||
Strikethrough?.Draw(spriteBatch, (int)Math.Ceiling(TextSize.X / 2f), pos.X,
|
||||
/* TODO: ???? */ForceUpperCase == ForceUpperCase.Yes ? pos.Y : pos.Y + GUI.Scale * 2f);
|
||||
}
|
||||
|
||||
if (overflowClipActive)
|
||||
|
||||
@@ -76,9 +76,6 @@ namespace Barotrauma
|
||||
private int selectionStartIndex;
|
||||
private int selectionEndIndex;
|
||||
private bool IsLeftToRight => selectionStartIndex <= selectionEndIndex;
|
||||
private Vector2 selectionStartPos;
|
||||
private Vector2 selectionEndPos;
|
||||
private Vector2 selectionRectSize;
|
||||
|
||||
private GUICustomComponent caretAndSelectionRenderer;
|
||||
|
||||
@@ -151,7 +148,7 @@ namespace Barotrauma
|
||||
maxTextLength = value;
|
||||
if (Text.Length > MaxTextLength)
|
||||
{
|
||||
SetText(textBlock.Text.Substring(0, (int)maxTextLength));
|
||||
SetText(Text.Substring(0, (int)maxTextLength));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -182,7 +179,7 @@ namespace Barotrauma
|
||||
set { textBlock.Censor = value; }
|
||||
}
|
||||
|
||||
public override string ToolTip
|
||||
public override RichString ToolTip
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -194,7 +191,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public override ScalableFont Font
|
||||
public override GUIFont Font
|
||||
{
|
||||
get { return textBlock?.Font ?? base.Font; }
|
||||
set
|
||||
@@ -247,7 +244,7 @@ namespace Barotrauma
|
||||
{
|
||||
get
|
||||
{
|
||||
return textBlock.Text;
|
||||
return textBlock.Text.SanitizedValue;
|
||||
}
|
||||
set
|
||||
{
|
||||
@@ -259,12 +256,12 @@ namespace Barotrauma
|
||||
|
||||
public string WrappedText
|
||||
{
|
||||
get { return textBlock.WrappedText; }
|
||||
get { return textBlock.WrappedText.Value; }
|
||||
}
|
||||
|
||||
public bool Readonly { get; set; }
|
||||
|
||||
public GUITextBox(RectTransform rectT, string text = "", Color? textColor = null, ScalableFont font = null,
|
||||
public GUITextBox(RectTransform rectT, string text = "", Color? textColor = null, GUIFont font = null,
|
||||
Alignment textAlignment = Alignment.Left, bool wrap = false, string style = "", Color? color = null, bool createClearButton = false, bool createPenIcon = true)
|
||||
: base(style, rectT)
|
||||
{
|
||||
@@ -273,9 +270,10 @@ namespace Barotrauma
|
||||
|
||||
this.color = color ?? Color.White;
|
||||
frame = new GUIFrame(new RectTransform(Vector2.One, rectT, Anchor.Center), style, color);
|
||||
GUI.Style.Apply(frame, style == "" ? "GUITextBox" : style);
|
||||
textBlock = new GUITextBlock(new RectTransform(Vector2.One, frame.RectTransform, Anchor.CenterLeft), text, textColor, font, textAlignment, wrap, playerInput: true);
|
||||
GUI.Style.Apply(textBlock, "", this);
|
||||
GUIStyle.Apply(frame, style == "" ? "GUITextBox" : style);
|
||||
textBlock = new GUITextBlock(new RectTransform(Vector2.One, frame.RectTransform, Anchor.CenterLeft), text ?? "", textColor, font, textAlignment, wrap, playerInput: true);
|
||||
GUIStyle.Apply(textBlock, "", this);
|
||||
if (font != null) { textBlock.Font = font; }
|
||||
CaretEnabled = true;
|
||||
caretPosDirty = true;
|
||||
|
||||
@@ -297,10 +295,11 @@ namespace Barotrauma
|
||||
clearButtonWidth = (int)(clearButton.Rect.Width * 1.2f);
|
||||
}
|
||||
|
||||
if (this.style != null && this.style.ChildStyles.ContainsKey("textboxicon") && createPenIcon)
|
||||
var selfStyle = Style;
|
||||
if (selfStyle != null && selfStyle.ChildStyles.ContainsKey("textboxicon".ToIdentifier()) && createPenIcon)
|
||||
{
|
||||
icon = new GUIImage(new RectTransform(new Vector2(0.6f, 0.6f), frame.RectTransform, Anchor.CenterRight, scaleBasis: ScaleBasis.BothHeight) { AbsoluteOffset = new Point(5 + clearButtonWidth, 0) }, null, scaleToFit: true);
|
||||
icon.ApplyStyle(this.style.ChildStyles["textboxicon"]);
|
||||
icon.ApplyStyle(this.Style.ChildStyles["textboxicon".ToIdentifier()]);
|
||||
textBlock.RectTransform.MaxSize = new Point(frame.Rect.Width - icon.Rect.Height - clearButtonWidth - icon.RectTransform.AbsoluteOffset.X * 2, int.MaxValue);
|
||||
}
|
||||
Font = textBlock.Font;
|
||||
@@ -325,53 +324,39 @@ namespace Barotrauma
|
||||
{
|
||||
text = textFilterFunction(text);
|
||||
}
|
||||
if (textBlock.Text == text) { return false; }
|
||||
if (Text == text) { return false; }
|
||||
textBlock.Text = text;
|
||||
if (textBlock.Text == null) textBlock.Text = "";
|
||||
if (textBlock.Text != "" && !Wrap)
|
||||
ClearSelection();
|
||||
if (Text == null) textBlock.Text = "";
|
||||
if (Text != "" && !Wrap)
|
||||
{
|
||||
if (maxTextLength != null)
|
||||
{
|
||||
if (textBlock.Text.Length > maxTextLength)
|
||||
{
|
||||
textBlock.Text = textBlock.Text.Substring(0, (int)maxTextLength);
|
||||
textBlock.Text = Text.Substring(0, (int)maxTextLength);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (ClampText && textBlock.Text.Length > 0 && Font.MeasureString(textBlock.Text).X * TextBlock.TextScale > (int)(textBlock.Rect.Width - textBlock.Padding.X - textBlock.Padding.Z))
|
||||
{
|
||||
textBlock.Text = textBlock.Text.Substring(0, textBlock.Text.Length - 1);
|
||||
textBlock.Text = Text.Substring(0, textBlock.Text.Length - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (store)
|
||||
{
|
||||
memento.Store(textBlock.Text);
|
||||
memento.Store(Text);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void CalculateCaretPos()
|
||||
{
|
||||
if (Censor || !Wrap)
|
||||
{
|
||||
string textDrawn = textBlock.CensoredText;
|
||||
CaretIndex = Math.Min(CaretIndex, textDrawn.Length);
|
||||
textDrawn = Censor ? textBlock.CensoredText : textBlock.Text;
|
||||
Vector2 textSize = Font.MeasureString(textDrawn[..CaretIndex]) * TextBlock.TextScale;
|
||||
caretPos = new Vector2(textSize.X, 0) + textBlock.TextPos - textBlock.Origin * TextBlock.TextScale;
|
||||
}
|
||||
else
|
||||
{
|
||||
CaretIndex = Math.Min(CaretIndex, textBlock.Text.Length);
|
||||
textBlock.Font.WrapText(
|
||||
textBlock.Text,
|
||||
(textBlock.Rect.Width - textBlock.Padding.X - textBlock.Padding.Z) / TextBlock.TextScale,
|
||||
CaretIndex,
|
||||
out Vector2 requestedCharPos);
|
||||
caretPos = requestedCharPos * TextBlock.TextScale + textBlock.TextPos - textBlock.Origin * TextBlock.TextScale;
|
||||
}
|
||||
CaretIndex = Math.Clamp(CaretIndex, 0, textBlock.Text.Length);
|
||||
var caretPositions = textBlock.GetAllCaretPositions();
|
||||
caretPos = caretPositions[CaretIndex];
|
||||
caretPosDirty = false;
|
||||
}
|
||||
|
||||
@@ -470,14 +455,19 @@ namespace Barotrauma
|
||||
{
|
||||
if (textBlock.OverflowClipActive)
|
||||
{
|
||||
if (CaretScreenPos.X < textBlock.Rect.X + textBlock.Padding.X)
|
||||
float left = textBlock.Rect.X + textBlock.Padding.X;
|
||||
if (CaretScreenPos.X < left)
|
||||
{
|
||||
textBlock.TextPos = new Vector2(textBlock.TextPos.X + ((textBlock.Rect.X + textBlock.Padding.X) - CaretScreenPos.X), textBlock.TextPos.Y);
|
||||
float diff = left - CaretScreenPos.X;
|
||||
textBlock.TextPos = new Vector2(textBlock.TextPos.X + diff, textBlock.TextPos.Y);
|
||||
CalculateCaretPos();
|
||||
}
|
||||
else if (CaretScreenPos.X > textBlock.Rect.Right - textBlock.Padding.Z)
|
||||
|
||||
float right = textBlock.Rect.Right - textBlock.Padding.Z;
|
||||
if (CaretScreenPos.X > right)
|
||||
{
|
||||
textBlock.TextPos = new Vector2(textBlock.TextPos.X - (CaretScreenPos.X - (textBlock.Rect.Right - textBlock.Padding.Z)), textBlock.TextPos.Y);
|
||||
float diff = CaretScreenPos.X - right;
|
||||
textBlock.TextPos = new Vector2(textBlock.TextPos.X - diff, textBlock.TextPos.Y);
|
||||
CalculateCaretPos();
|
||||
}
|
||||
}
|
||||
@@ -509,74 +499,57 @@ namespace Barotrauma
|
||||
private void DrawCaretAndSelection(SpriteBatch spriteBatch, GUICustomComponent customComponent)
|
||||
{
|
||||
if (!Visible) { return; }
|
||||
if (Selected)
|
||||
if (!Selected) { return; }
|
||||
|
||||
if (caretVisible)
|
||||
{
|
||||
if (caretVisible )
|
||||
{
|
||||
GUI.DrawLine(spriteBatch,
|
||||
new Vector2(Rect.X + (int)caretPos.X + 2, Rect.Y + caretPos.Y + 3),
|
||||
new Vector2(Rect.X + (int)caretPos.X + 2, Rect.Y + caretPos.Y + Font.MeasureString("I").Y * textBlock.TextScale - 3),
|
||||
CaretColor ?? textBlock.TextColor * (textBlock.TextColor.A / 255.0f));
|
||||
}
|
||||
if (selectedCharacters > 0)
|
||||
{
|
||||
DrawSelectionRect(spriteBatch);
|
||||
}
|
||||
//GUI.DrawString(spriteBatch, new Vector2(100, 0), selectedCharacters.ToString(), Color.LightBlue, Color.Black);
|
||||
//GUI.DrawString(spriteBatch, new Vector2(100, 20), selectionStartIndex.ToString(), Color.White, Color.Black);
|
||||
//GUI.DrawString(spriteBatch, new Vector2(140, 20), selectionEndIndex.ToString(), Color.White, Color.Black);
|
||||
//GUI.DrawString(spriteBatch, new Vector2(100, 40), selectedText.ToString(), Color.Yellow, Color.Black);
|
||||
//GUI.DrawString(spriteBatch, new Vector2(100, 60), $"caret index: {CaretIndex.ToString()}", GUI.Style.Red, Color.Black);
|
||||
//GUI.DrawString(spriteBatch, new Vector2(100, 80), $"caret pos: {caretPos.ToString()}", GUI.Style.Red, Color.Black);
|
||||
//GUI.DrawString(spriteBatch, new Vector2(100, 100), $"caret screen pos: {CaretScreenPos.ToString()}", GUI.Style.Red, Color.Black);
|
||||
//GUI.DrawString(spriteBatch, new Vector2(100, 120), $"text start pos: {(textBlock.TextPos - textBlock.Origin).ToString()}", Color.White, Color.Black);
|
||||
//GUI.DrawString(spriteBatch, new Vector2(100, 140), $"cursor pos: {PlayerInput.MousePosition.ToString()}", Color.White, Color.Black);
|
||||
GUI.DrawLine(spriteBatch,
|
||||
new Vector2(Rect.X + (int)caretPos.X + 2, Rect.Y + caretPos.Y + 3),
|
||||
new Vector2(Rect.X + (int)caretPos.X + 2, Rect.Y + caretPos.Y + Font.LineHeight * textBlock.TextScale - 3),
|
||||
CaretColor ?? textBlock.TextColor * (textBlock.TextColor.A / 255.0f));
|
||||
}
|
||||
if (selectedCharacters > 0)
|
||||
{
|
||||
DrawSelectionRect(spriteBatch);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawSelectionRect(SpriteBatch spriteBatch)
|
||||
{
|
||||
if (textBlock.WrappedText.Contains("\n"))
|
||||
{
|
||||
// Multiline selection
|
||||
var characterPositions = textBlock.GetAllCaretPositions();
|
||||
(int startIndex, int endIndex) = selectionStartIndex < selectionEndIndex
|
||||
? (selectionStartIndex, selectionEndIndex)
|
||||
: (selectionEndIndex, selectionStartIndex);
|
||||
endIndex--;
|
||||
var characterPositions = textBlock.GetAllCaretPositions();
|
||||
(int startIndex, int endIndex) = IsLeftToRight
|
||||
? (selectionStartIndex, selectionEndIndex)
|
||||
: (selectionEndIndex, selectionStartIndex);
|
||||
endIndex--;
|
||||
|
||||
void drawRect(Vector2 topLeft, Vector2 bottomRight)
|
||||
{
|
||||
int minWidth = GUI.IntScale(5);
|
||||
if (bottomRight.X - topLeft.X < minWidth) { bottomRight.X = topLeft.X + minWidth; }
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
Rect.Location.ToVector2() + topLeft,
|
||||
bottomRight - topLeft,
|
||||
SelectionColor, isFilled: true);
|
||||
}
|
||||
|
||||
Vector2 topLeft = characterPositions[startIndex];
|
||||
for (int i = startIndex+1; i <= endIndex; i++)
|
||||
{
|
||||
Vector2 currPos = characterPositions[i];
|
||||
if (!MathUtils.NearlyEqual(topLeft.Y, currPos.Y))
|
||||
{
|
||||
Vector2 bottomRight = characterPositions[i - 1];
|
||||
bottomRight += Font.MeasureChar(Text[i - 1]);
|
||||
drawRect(topLeft, bottomRight);
|
||||
topLeft = currPos;
|
||||
}
|
||||
}
|
||||
Vector2 finalBottomRight = characterPositions[endIndex];
|
||||
finalBottomRight += Font.MeasureChar(Text[endIndex]);
|
||||
drawRect(topLeft, finalBottomRight);
|
||||
}
|
||||
else
|
||||
void drawRect(Vector2 topLeft, Vector2 bottomRight)
|
||||
{
|
||||
// Single line selection
|
||||
Vector2 topLeft = IsLeftToRight ? selectionStartPos : selectionEndPos;
|
||||
GUI.DrawRectangle(spriteBatch, Rect.Location.ToVector2() + topLeft, selectionRectSize, SelectionColor, isFilled: true);
|
||||
int minWidth = GUI.IntScale(5);
|
||||
if (bottomRight.X - topLeft.X < minWidth) { bottomRight.X = topLeft.X + minWidth; }
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
Rect.Location.ToVector2() + topLeft,
|
||||
bottomRight - topLeft,
|
||||
SelectionColor, isFilled: true);
|
||||
}
|
||||
|
||||
Vector2 topLeft = characterPositions[startIndex];
|
||||
for (int i = startIndex+1; i <= endIndex; i++)
|
||||
{
|
||||
Vector2 currPos = characterPositions[i];
|
||||
if (!MathUtils.NearlyEqual(topLeft.Y, currPos.Y))
|
||||
{
|
||||
Vector2 bottomRight = characterPositions[i - 1];
|
||||
bottomRight += Font.MeasureChar(Text[i - 1]) * TextBlock.TextScale;
|
||||
drawRect(topLeft, bottomRight);
|
||||
topLeft = currPos;
|
||||
}
|
||||
}
|
||||
Vector2 finalBottomRight = characterPositions[endIndex];
|
||||
if (Text.Length > endIndex)
|
||||
{
|
||||
finalBottomRight += Font.MeasureChar(Text[endIndex]) * TextBlock.TextScale;
|
||||
}
|
||||
drawRect(topLeft, finalBottomRight);
|
||||
}
|
||||
|
||||
public void ReceiveTextInput(char inputChar)
|
||||
@@ -710,8 +683,8 @@ namespace Barotrauma
|
||||
float lineHeight = Font.LineHeight * TextBlock.TextScale;
|
||||
int newIndex = textBlock.GetCaretIndexFromLocalPos(new Vector2(caretPos.X, caretPos.Y - lineHeight * 0.5f));
|
||||
textBlock.Font.WrapText(
|
||||
textBlock.Text,
|
||||
(textBlock.Rect.Width - textBlock.Padding.X - textBlock.Padding.Z) / TextBlock.TextScale,
|
||||
textBlock.Text.SanitizedValue,
|
||||
GetWrapWidth(),
|
||||
newIndex,
|
||||
out Vector2 requestedCharPos);
|
||||
requestedCharPos *= TextBlock.TextScale;
|
||||
@@ -728,8 +701,8 @@ namespace Barotrauma
|
||||
lineHeight = Font.LineHeight * TextBlock.TextScale;
|
||||
newIndex = textBlock.GetCaretIndexFromLocalPos(new Vector2(caretPos.X, caretPos.Y + lineHeight * 1.5f));
|
||||
textBlock.Font.WrapText(
|
||||
textBlock.Text,
|
||||
(textBlock.Rect.Width - textBlock.Padding.X - textBlock.Padding.Z) / TextBlock.TextScale,
|
||||
textBlock.Text.SanitizedValue,
|
||||
GetWrapWidth(),
|
||||
newIndex,
|
||||
out Vector2 requestedCharPos2);
|
||||
requestedCharPos2 *= TextBlock.TextScale;
|
||||
@@ -816,7 +789,6 @@ namespace Barotrauma
|
||||
{
|
||||
CaretIndex = 0;
|
||||
CalculateCaretPos();
|
||||
selectionStartPos = caretPos;
|
||||
selectionStartIndex = 0;
|
||||
CaretIndex = Text.Length;
|
||||
CalculateSelection();
|
||||
@@ -847,15 +819,18 @@ namespace Barotrauma
|
||||
{
|
||||
if (selectedText.Length == 0) { return; }
|
||||
|
||||
selectionStartIndex = Math.Max(0, Math.Min(selectionEndIndex, Math.Min(selectionStartIndex, Text.Length - 1)));
|
||||
int selectionLength = Math.Min(Text.Length - selectionStartIndex, selectedText.Length);
|
||||
SetText(Text.Remove(selectionStartIndex, selectionLength));
|
||||
CaretIndex = Math.Min(Text.Length, selectionStartIndex);
|
||||
int targetCaretIndex = Math.Max(0, Math.Min(selectionEndIndex, Math.Min(selectionStartIndex, Text.Length - 1)));
|
||||
int selectionLength = Math.Min(Text.Length - targetCaretIndex, selectedText.Length);
|
||||
SetText(Text.Remove(targetCaretIndex, selectionLength));
|
||||
CaretIndex = targetCaretIndex;
|
||||
|
||||
ClearSelection();
|
||||
OnTextChanged?.Invoke(this, Text);
|
||||
}
|
||||
|
||||
private float GetWrapWidth()
|
||||
=> Wrap ? (textBlock.Rect.Width - textBlock.Padding.X - textBlock.Padding.Z) / TextBlock.TextScale : float.PositiveInfinity;
|
||||
|
||||
private void InitSelectionStart()
|
||||
{
|
||||
if (caretPosDirty)
|
||||
@@ -865,29 +840,20 @@ namespace Barotrauma
|
||||
if (selectionStartIndex == -1)
|
||||
{
|
||||
selectionStartIndex = CaretIndex;
|
||||
selectionStartPos = caretPos;
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateSelection()
|
||||
{
|
||||
string textDrawn = Censor ? textBlock.CensoredText : textBlock.WrappedText;
|
||||
string textDrawn = Censor ? textBlock.CensoredText : WrappedText;
|
||||
InitSelectionStart();
|
||||
selectionEndIndex = Math.Min(CaretIndex, textDrawn.Length);
|
||||
selectionEndPos = caretPos;
|
||||
selectedCharacters = Math.Abs(selectionStartIndex - selectionEndIndex);
|
||||
try
|
||||
{
|
||||
if (IsLeftToRight)
|
||||
{
|
||||
selectedText = Text.Substring(selectionStartIndex, Math.Min(selectedCharacters, Text.Length));
|
||||
selectionRectSize = Font.MeasureString(textDrawn.Substring(selectionStartIndex, Math.Min(selectedCharacters, textDrawn.Length))) * TextBlock.TextScale;
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedText = Text.Substring(selectionEndIndex, Math.Min(selectedCharacters, Text.Length));
|
||||
selectionRectSize = Font.MeasureString(textDrawn.Substring(selectionEndIndex, Math.Min(selectedCharacters, textDrawn.Length))) * TextBlock.TextScale;
|
||||
}
|
||||
selectedText = Text.Substring(
|
||||
IsLeftToRight ? selectionStartIndex : selectionEndIndex,
|
||||
Math.Min(selectedCharacters, Text.Length));
|
||||
}
|
||||
catch (ArgumentOutOfRangeException exception)
|
||||
{
|
||||
|
||||
@@ -20,18 +20,18 @@ namespace Barotrauma
|
||||
|
||||
public override bool Selected
|
||||
{
|
||||
get { return selected; }
|
||||
get { return isSelected; }
|
||||
set
|
||||
{
|
||||
if (value == selected) { return; }
|
||||
if (value == isSelected) { return; }
|
||||
if (radioButtonGroup != null && radioButtonGroup.SelectedRadioButton == this)
|
||||
{
|
||||
selected = true;
|
||||
isSelected = true;
|
||||
return;
|
||||
}
|
||||
|
||||
selected = value;
|
||||
State = selected ? ComponentState.Selected : ComponentState.None;
|
||||
isSelected = value;
|
||||
State = isSelected ? ComponentState.Selected : ComponentState.None;
|
||||
if (value && radioButtonGroup != null)
|
||||
{
|
||||
radioButtonGroup.SelectRadioButton(this);
|
||||
@@ -88,7 +88,7 @@ namespace Barotrauma
|
||||
}
|
||||
}*/
|
||||
|
||||
public override ScalableFont Font
|
||||
public override GUIFont Font
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -112,7 +112,7 @@ namespace Barotrauma
|
||||
get { return text; }
|
||||
}
|
||||
|
||||
public override string ToolTip
|
||||
public override RichString ToolTip
|
||||
{
|
||||
get { return base.ToolTip; }
|
||||
set
|
||||
@@ -123,13 +123,13 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public string Text
|
||||
public LocalizedString Text
|
||||
{
|
||||
get { return text.Text; }
|
||||
set { text.Text = value; }
|
||||
}
|
||||
|
||||
public GUITickBox(RectTransform rectT, string label, ScalableFont font = null, string style = "") : base(null, rectT)
|
||||
public GUITickBox(RectTransform rectT, LocalizedString label, GUIFont font = null, string style = "") : base(null, rectT)
|
||||
{
|
||||
CanBeFocused = true;
|
||||
HoverCursor = CursorState.Hand;
|
||||
@@ -145,7 +145,7 @@ namespace Barotrauma
|
||||
SelectedColor = Color.DarkGray,
|
||||
CanBeFocused = false
|
||||
};
|
||||
GUI.Style.Apply(box, style == "" ? "GUITickBox" : style);
|
||||
GUIStyle.Apply(box, style == "" ? "GUITickBox" : style);
|
||||
if (box.RectTransform.MinSize.Y > 0)
|
||||
{
|
||||
RectTransform.MinSize = box.RectTransform.MinSize;
|
||||
@@ -159,7 +159,7 @@ namespace Barotrauma
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
GUI.Style.Apply(text, "GUITextBlock", this);
|
||||
GUIStyle.Apply(text, "GUITextBlock", this);
|
||||
Enabled = true;
|
||||
|
||||
ResizeBox();
|
||||
@@ -205,13 +205,13 @@ namespace Barotrauma
|
||||
{
|
||||
Selected = !Selected;
|
||||
}
|
||||
else if (!selected)
|
||||
else if (!isSelected)
|
||||
{
|
||||
Selected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (selected)
|
||||
else if (isSelected)
|
||||
{
|
||||
State = ComponentState.Selected;
|
||||
}
|
||||
|
||||
@@ -90,7 +90,8 @@ namespace Barotrauma
|
||||
if (GameMain.Instance != null)
|
||||
{
|
||||
GameMain.Instance.ResolutionChanged += CreateAreas;
|
||||
GameMain.Config.OnHUDScaleChanged += CreateAreas;
|
||||
#warning TODO: reimplement
|
||||
//GameSettings.CurrentConfig.OnHUDScaleChanged += CreateAreas;
|
||||
CreateAreas();
|
||||
CharacterInfo.Init();
|
||||
}
|
||||
@@ -163,7 +164,7 @@ namespace Barotrauma
|
||||
public static void Draw(SpriteBatch spriteBatch)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, ButtonAreaTop, Color.White * 0.5f);
|
||||
GUI.DrawRectangle(spriteBatch, MessageAreaTop, GUI.Style.Orange * 0.5f);
|
||||
GUI.DrawRectangle(spriteBatch, MessageAreaTop, GUIStyle.Orange * 0.5f);
|
||||
GUI.DrawRectangle(spriteBatch, CrewArea, Color.Blue * 0.5f);
|
||||
GUI.DrawRectangle(spriteBatch, ChatBoxArea, Color.Cyan * 0.5f);
|
||||
GUI.DrawRectangle(spriteBatch, HealthBarArea, Color.Red * 0.5f);
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.Xml.Linq;
|
||||
using Barotrauma.Media;
|
||||
using System.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -69,14 +70,10 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private string selectedTip;
|
||||
private List<RichTextData> selectedTipRichTextData;
|
||||
private bool selectedTipRichTextUnparsed;
|
||||
private void SetSelectedTip(string tip)
|
||||
private RichString selectedTip;
|
||||
private void SetSelectedTip(LocalizedString tip)
|
||||
{
|
||||
selectedTip = tip;
|
||||
selectedTipRichTextData = null;
|
||||
selectedTipRichTextUnparsed = true;
|
||||
selectedTip = RichString.Rich(tip);
|
||||
}
|
||||
|
||||
private readonly object loadMutex = new object();
|
||||
@@ -113,6 +110,8 @@ namespace Barotrauma
|
||||
set;
|
||||
}
|
||||
|
||||
public LanguageIdentifier[] AvailableLanguages = null;
|
||||
|
||||
public LoadingScreen(GraphicsDevice graphics)
|
||||
{
|
||||
defaultBackgroundTexture = TextureLoader.FromFile("Content/Map/LocationPortraits/AlienRuins.png");
|
||||
@@ -123,12 +122,12 @@ namespace Barotrauma
|
||||
overlay = TextureLoader.FromFile("Content/UI/LoadingScreenOverlay.png");
|
||||
noiseSprite = new Sprite("Content/UI/noise.png", Vector2.Zero);
|
||||
DrawLoadingText = true;
|
||||
SetSelectedTip(TextManager.Get("LoadingScreenTip", true));
|
||||
SetSelectedTip(TextManager.Get("LoadingScreenTip"));
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, GraphicsDevice graphics, float deltaTime)
|
||||
{
|
||||
if (GameMain.Config.EnableSplashScreen)
|
||||
if (GameSettings.CurrentConfig.EnableSplashScreen)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -138,11 +137,11 @@ namespace Barotrauma
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Playing splash screen video failed", e);
|
||||
GameMain.Config.EnableSplashScreen = false;
|
||||
DisableSplashScreen();
|
||||
}
|
||||
}
|
||||
|
||||
var titleStyle = GUI.Style?.GetComponentStyle("TitleText");
|
||||
|
||||
var titleStyle = GUIStyle.GetComponentStyle("TitleText");
|
||||
Sprite titleSprite = null;
|
||||
if (!WaitForLanguageSelection && titleStyle != null && titleStyle.Sprites.ContainsKey(GUIComponent.ComponentState.None))
|
||||
{
|
||||
@@ -187,67 +186,58 @@ namespace Barotrauma
|
||||
}
|
||||
else if (DrawLoadingText)
|
||||
{
|
||||
if (TextManager.Initialized)
|
||||
LocalizedString loadText;
|
||||
if (LoadState == 100.0f)
|
||||
{
|
||||
string loadText;
|
||||
if (LoadState == 100.0f)
|
||||
#if DEBUG
|
||||
if (GameSettings.CurrentConfig.AutomaticQuickStartEnabled || GameSettings.CurrentConfig.AutomaticCampaignLoadEnabled || (GameSettings.CurrentConfig.TestScreenEnabled && GameMain.FirstLoad))
|
||||
{
|
||||
#if DEBUG
|
||||
if (GameMain.Config.AutomaticQuickStartEnabled || GameMain.Config.AutomaticCampaignLoadEnabled || GameMain.Config.TestScreenEnabled && GameMain.FirstLoad)
|
||||
{
|
||||
loadText = "QUICKSTARTING ...";
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
loadText = TextManager.Get("PressAnyKey");
|
||||
#if DEBUG
|
||||
}
|
||||
#endif
|
||||
loadText = "QUICKSTARTING ...";
|
||||
}
|
||||
else
|
||||
{
|
||||
loadText = TextManager.Get("Loading");
|
||||
if (LoadState != null)
|
||||
{
|
||||
loadText += " " + (int)LoadState + " %";
|
||||
#endif
|
||||
loadText = TextManager.Get("PressAnyKey");
|
||||
#if DEBUG
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
loadText = TextManager.Get("Loading");
|
||||
if (LoadState != null)
|
||||
{
|
||||
loadText += " " + (int)LoadState + " %";
|
||||
|
||||
#if DEBUG
|
||||
if (GameMain.FirstLoad && GameMain.CancelQuickStart)
|
||||
{
|
||||
loadText += " (Quickstart aborted)";
|
||||
}
|
||||
#endif
|
||||
if (GameMain.FirstLoad && GameMain.CancelQuickStart)
|
||||
{
|
||||
loadText += " (Quickstart aborted)";
|
||||
}
|
||||
}
|
||||
if (GUI.LargeFont != null)
|
||||
{
|
||||
GUI.LargeFont.DrawString(spriteBatch, loadText.ToUpper(),
|
||||
new Vector2(GameMain.GraphicsWidth / 2.0f - GUI.LargeFont.MeasureString(loadText.ToUpper()).X / 2.0f, GameMain.GraphicsHeight * 0.75f),
|
||||
Color.White);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (GUI.Font != null && selectedTip != null)
|
||||
if (GUIStyle.LargeFont.HasValue)
|
||||
{
|
||||
if (selectedTipRichTextUnparsed)
|
||||
{
|
||||
selectedTipRichTextData = RichTextData.GetRichTextData(selectedTip, out selectedTip);
|
||||
selectedTipRichTextUnparsed = false;
|
||||
}
|
||||
GUIStyle.LargeFont.DrawString(spriteBatch, loadText.ToUpper(),
|
||||
new Vector2(GameMain.GraphicsWidth / 2.0f - GUIStyle.LargeFont.MeasureString(loadText.ToUpper()).X / 2.0f, GameMain.GraphicsHeight * 0.75f),
|
||||
Color.White);
|
||||
}
|
||||
|
||||
string wrappedTip = ToolBox.WrapText(selectedTip, GameMain.GraphicsWidth * 0.5f, GUI.Font);
|
||||
if (GUIStyle.Font.HasValue && selectedTip != null)
|
||||
{
|
||||
string wrappedTip = ToolBox.WrapText(selectedTip.SanitizedValue, GameMain.GraphicsWidth * 0.5f, GUIStyle.Font.Value);
|
||||
string[] lines = wrappedTip.Split('\n');
|
||||
float lineHeight = GUI.Font.MeasureString(selectedTip).Y;
|
||||
float lineHeight = GUIStyle.Font.MeasureString(selectedTip).Y;
|
||||
|
||||
if (selectedTipRichTextData != null)
|
||||
if (selectedTip.RichTextData != null)
|
||||
{
|
||||
int rtdOffset = 0;
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
GUI.Font.DrawStringWithColors(spriteBatch, lines[i],
|
||||
new Vector2((int)(GameMain.GraphicsWidth / 2.0f - GUI.Font.MeasureString(lines[i]).X / 2.0f), (int)(GameMain.GraphicsHeight * 0.8f + i * lineHeight)), Color.White,
|
||||
0f, Vector2.Zero, 1f, SpriteEffects.None, 0f, selectedTipRichTextData, rtdOffset);
|
||||
GUIStyle.Font.DrawStringWithColors(spriteBatch, lines[i],
|
||||
new Vector2((int)(GameMain.GraphicsWidth / 2.0f - GUIStyle.Font.MeasureString(lines[i]).X / 2.0f), (int)(GameMain.GraphicsHeight * 0.8f + i * lineHeight)), Color.White,
|
||||
0f, Vector2.Zero, 1f, SpriteEffects.None, 0f, selectedTip.RichTextData.Value, rtdOffset);
|
||||
rtdOffset += lines[i].Length;
|
||||
}
|
||||
}
|
||||
@@ -255,8 +245,8 @@ namespace Barotrauma
|
||||
{
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
GUI.Font.DrawString(spriteBatch, lines[i],
|
||||
new Vector2((int)(GameMain.GraphicsWidth / 2.0f - GUI.Font.MeasureString(lines[i]).X / 2.0f), (int)(GameMain.GraphicsHeight * 0.8f + i * lineHeight)), Color.White);
|
||||
GUIStyle.Font.DrawString(spriteBatch, lines[i],
|
||||
new Vector2((int)(GameMain.GraphicsWidth / 2.0f - GUIStyle.Font.MeasureString(lines[i]).X / 2.0f), (int)(GameMain.GraphicsHeight * 0.8f + i * lineHeight)), Color.White);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -280,7 +270,7 @@ namespace Barotrauma
|
||||
if (noiseVal < 0.2f)
|
||||
{
|
||||
//SCP-CB reference
|
||||
randText = (new string[] { "NIL", "black white gray", "Sometimes we would have had time to scream", "e8m106]af", "NO" }).GetRandom();
|
||||
randText = (new string[] { "NIL", "black white gray", "Sometimes we would have had time to scream", "e8m106]af", "NO" }).GetRandomUnsynced();
|
||||
}
|
||||
else if (noiseVal < 0.3f)
|
||||
{
|
||||
@@ -295,15 +285,20 @@ namespace Barotrauma
|
||||
Rand.Int(100).ToString().PadLeft(2, '0');
|
||||
}
|
||||
|
||||
GUI.LargeFont?.DrawString(spriteBatch, randText,
|
||||
new Vector2(GameMain.GraphicsWidth - decorativeMap.FrameSize.X * decorativeScale.X * 0.8f, GameMain.GraphicsHeight * 0.57f),
|
||||
Color.White * (1.0f - noiseVal));
|
||||
if (GUIStyle.LargeFont.HasValue)
|
||||
{
|
||||
GUIStyle.LargeFont.DrawString(spriteBatch, randText,
|
||||
new Vector2(GameMain.GraphicsWidth - decorativeMap.FrameSize.X * decorativeScale.X * 0.8f, GameMain.GraphicsHeight * 0.57f),
|
||||
Color.White * (1.0f - noiseVal));
|
||||
}
|
||||
|
||||
spriteBatch.End();
|
||||
}
|
||||
|
||||
private void DrawLanguageSelectionPrompt(SpriteBatch spriteBatch, GraphicsDevice graphicsDevice)
|
||||
{
|
||||
if (AvailableLanguages is null) { return; }
|
||||
|
||||
if (languageSelectionFont == null)
|
||||
{
|
||||
languageSelectionFont = new ScalableFont("Content/Fonts/NotoSans/NotoSans-Bold.ttf",
|
||||
@@ -320,8 +315,8 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
Vector2 textPos = new Vector2(GameMain.GraphicsWidth / 2, GameMain.GraphicsHeight * 0.3f);
|
||||
Vector2 textSpacing = new Vector2(0.0f, (GameMain.GraphicsHeight * 0.5f) / TextManager.AvailableLanguages.Count());
|
||||
foreach (string language in TextManager.AvailableLanguages)
|
||||
Vector2 textSpacing = new Vector2(0.0f, (GameMain.GraphicsHeight * 0.5f) / AvailableLanguages.Length);
|
||||
foreach (LanguageIdentifier language in AvailableLanguages)
|
||||
{
|
||||
string localizedLanguageName = TextManager.GetTranslatedLanguageName(language);
|
||||
var font = TextManager.IsCJK(localizedLanguageName) ? languageSelectionFontCJK : languageSelectionFont;
|
||||
@@ -335,11 +330,11 @@ namespace Barotrauma
|
||||
hover ? Color.White : Color.White * 0.6f);
|
||||
if (hover && PlayerInput.PrimaryMouseButtonClicked())
|
||||
{
|
||||
GameMain.Config.Language = language;
|
||||
var config = GameSettings.CurrentConfig;
|
||||
config.Language = language;
|
||||
GameSettings.SetCurrentConfig(config);
|
||||
//reload tip in the selected language
|
||||
SetSelectedTip(TextManager.Get("LoadingScreenTip", true));
|
||||
GameMain.Config.SetDefaultBindings(legacy: false);
|
||||
GameMain.Config.CheckBindings(useDefaults: true);
|
||||
SetSelectedTip(TextManager.Get("LoadingScreenTip"));
|
||||
WaitForLanguageSelection = false;
|
||||
languageSelectionFont?.Dispose(); languageSelectionFont = null;
|
||||
languageSelectionFontCJK?.Dispose(); languageSelectionFontCJK = null;
|
||||
@@ -368,7 +363,7 @@ namespace Barotrauma
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
GameMain.Config.EnableSplashScreen = false;
|
||||
DisableSplashScreen();
|
||||
DebugConsole.ThrowError("Playing the splash screen \"" + fileName + "\" failed.", e);
|
||||
PendingSplashScreens.Clear();
|
||||
currSplashScreen = null;
|
||||
@@ -425,13 +420,20 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private void DisableSplashScreen()
|
||||
{
|
||||
var config = GameSettings.CurrentConfig;
|
||||
config.EnableSplashScreen = false;
|
||||
GameSettings.SetCurrentConfig(config);
|
||||
}
|
||||
|
||||
bool drawn;
|
||||
public IEnumerable<CoroutineStatus> DoLoading(IEnumerable<CoroutineStatus> loader)
|
||||
{
|
||||
drawn = false;
|
||||
LoadState = null;
|
||||
SetSelectedTip(TextManager.Get("LoadingScreenTip", true));
|
||||
currentBackgroundTexture = LocationType.List.GetRandom()?.GetPortrait(Rand.Int(int.MaxValue))?.Texture;
|
||||
SetSelectedTip(TextManager.Get("LoadingScreenTip"));
|
||||
currentBackgroundTexture = LocationType.Prefabs.GetRandomUnsynced()?.GetPortrait(Rand.Int(int.MaxValue))?.Texture;
|
||||
|
||||
while (!drawn)
|
||||
{
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Barotrauma
|
||||
Afflictions = new List<PendingAfflictionElement>();
|
||||
}
|
||||
|
||||
public PendingAfflictionElement? FindAfflictionElement(MedicalClinic.NetAffliction target) => Afflictions.FirstOrNull(element => element.Target.Identifier.Equals(target.Identifier, StringComparison.OrdinalIgnoreCase));
|
||||
public PendingAfflictionElement? FindAfflictionElement(MedicalClinic.NetAffliction target) => Afflictions.FirstOrNull(element => element.Target.Identifier == target.Identifier);
|
||||
}
|
||||
|
||||
// Represents an affliction on the left side crew entry
|
||||
@@ -268,12 +268,12 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
int totalCost = medicalClinic.GetTotalCost();
|
||||
healList.PriceBlock.Text = UpgradeStore.FormatCurrency(totalCost);
|
||||
healList.PriceBlock.TextColor = GUI.Style.Red;
|
||||
healList.PriceBlock.Text = TextManager.FormatCurrency(totalCost);
|
||||
healList.PriceBlock.TextColor = GUIStyle.Red;
|
||||
healList.HealButton.Enabled = false;
|
||||
if (medicalClinic.GetMoney() > totalCost)
|
||||
if (medicalClinic.GetWallet().CanAfford(totalCost))
|
||||
{
|
||||
healList.PriceBlock.TextColor = GUI.Style.TextColor;
|
||||
healList.PriceBlock.TextColor = GUIStyle.TextColorNormal;
|
||||
if (medicalClinic.PendingHeals.Any())
|
||||
{
|
||||
healList.HealButton.Enabled = true;
|
||||
@@ -288,7 +288,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (element.FindAfflictionElement(affliction) is { } existingAffliction)
|
||||
{
|
||||
existingAffliction.Price.Text = UpgradeStore.FormatCurrency(affliction.Strength);
|
||||
existingAffliction.Price.Text = TextManager.FormatCurrency(affliction.Strength);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -443,7 +443,7 @@ namespace Barotrauma
|
||||
|
||||
GUILayoutGroup clinicLabelLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.1f), clinicContent.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft);
|
||||
GUIImage clinicIcon = new GUIImage(new RectTransform(Vector2.One, clinicLabelLayout.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "CrewManagementHeaderIcon", scaleToFit: true);
|
||||
GUITextBlock clinicLabel = new GUITextBlock(new RectTransform(Vector2.One, clinicLabelLayout.RectTransform), TextManager.Get("medicalclinic.medicalclinic"), font: GUI.LargeFont);
|
||||
GUITextBlock clinicLabel = new GUITextBlock(new RectTransform(Vector2.One, clinicLabelLayout.RectTransform), TextManager.Get("medicalclinic.medicalclinic"), font: GUIStyle.LargeFont);
|
||||
|
||||
GUIFrame clinicBackground = new GUIFrame(new RectTransform(Vector2.One, clinicContent.RectTransform));
|
||||
|
||||
@@ -459,15 +459,15 @@ namespace Barotrauma
|
||||
};
|
||||
|
||||
GUILayoutGroup balanceLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.1f), crewContent.RectTransform));
|
||||
GUITextBlock balanceLabel = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), balanceLayout.RectTransform), TextManager.Get("campaignstore.balance"), textAlignment: Alignment.BottomRight, font: GUI.Font)
|
||||
GUITextBlock balanceLabel = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), balanceLayout.RectTransform), TextManager.Get("campaignstore.balance"), textAlignment: Alignment.BottomRight, font: GUIStyle.Font)
|
||||
{
|
||||
AutoScaleVertical = true,
|
||||
ForceUpperCase = true
|
||||
ForceUpperCase = ForceUpperCase.Yes
|
||||
};
|
||||
|
||||
GUITextBlock moneyLabel = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), balanceLayout.RectTransform), string.Empty, textAlignment: Alignment.TopRight, font: GUI.Style.SubHeadingFont)
|
||||
GUITextBlock moneyLabel = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), balanceLayout.RectTransform), string.Empty, textAlignment: Alignment.TopRight, font: GUIStyle.SubHeadingFont)
|
||||
{
|
||||
TextGetter = () => UpgradeStore.FormatCurrency(medicalClinic.GetMoney()),
|
||||
TextGetter = () => TextManager.FormatCurrency(medicalClinic.GetWallet().Balance),
|
||||
AutoScaleVertical = true,
|
||||
TextScale = 1.1f
|
||||
};
|
||||
@@ -519,18 +519,18 @@ namespace Barotrauma
|
||||
|
||||
GUILayoutGroup healthLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.1f, 1f), crewLayout.RectTransform), isHorizontal: true, Anchor.Center);
|
||||
|
||||
new GUITextBlock(new RectTransform(Vector2.One, healthLayout.RectTransform), string.Empty, textAlignment: Alignment.Center, font: GUI.SubHeadingFont)
|
||||
new GUITextBlock(new RectTransform(Vector2.One, healthLayout.RectTransform), string.Empty, textAlignment: Alignment.Center, font: GUIStyle.SubHeadingFont)
|
||||
{
|
||||
TextGetter = () => $"{(int)(info.Character?.HealthPercentage ?? 100f)}%",
|
||||
TextColor = GUI.Style.Green
|
||||
TextGetter = () => TextManager.GetWithVariable("percentageformat", "[value]", $"{(int)(info.Character?.HealthPercentage ?? 100f)}"),
|
||||
TextColor = GUIStyle.Green
|
||||
};
|
||||
|
||||
GUITextBlock overflowIndicator =
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.25f, 1f), afflictionList.Content.RectTransform, scaleBasis: ScaleBasis.BothHeight), text: "+", textAlignment: Alignment.Center, font: GUI.LargeFont)
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.25f, 1f), afflictionList.Content.RectTransform, scaleBasis: ScaleBasis.BothHeight), text: "+", textAlignment: Alignment.Center, font: GUIStyle.LargeFont)
|
||||
{
|
||||
Visible = false,
|
||||
CanBeFocused = false,
|
||||
TextColor = GUI.Style.Red
|
||||
TextColor = GUIStyle.Red
|
||||
};
|
||||
|
||||
MedicalClinic.NetCrewMember member = new MedicalClinic.NetCrewMember { CharacterInfo = info, Afflictions = Array.Empty<MedicalClinic.NetAffliction>() };
|
||||
@@ -552,13 +552,13 @@ namespace Barotrauma
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1f, 0.05f), pendingHealContainer.RectTransform), TextManager.Get("medicalclinic.pendingheals"), font: GUI.SubHeadingFont);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1f, 0.05f), pendingHealContainer.RectTransform), TextManager.Get("medicalclinic.pendingheals"), font: GUIStyle.SubHeadingFont);
|
||||
|
||||
GUIFrame healListContainer = new GUIFrame(new RectTransform(new Vector2(1f, 0.9f), pendingHealContainer.RectTransform), style: null);
|
||||
GUITextBlock? errorBlock = null;
|
||||
if (!GameMain.IsSingleplayer)
|
||||
{
|
||||
errorBlock = new GUITextBlock(new RectTransform(Vector2.One, healListContainer.RectTransform), text: TextManager.Get("pleasewaitupnp"), font: GUI.LargeFont, textAlignment: Alignment.Center);
|
||||
errorBlock = new GUITextBlock(new RectTransform(Vector2.One, healListContainer.RectTransform), text: TextManager.Get("pleasewaitupnp"), font: GUIStyle.LargeFont, textAlignment: Alignment.Center);
|
||||
}
|
||||
|
||||
GUIListBox healList = new GUIListBox(new RectTransform(Vector2.One, healListContainer.RectTransform))
|
||||
@@ -571,13 +571,13 @@ namespace Barotrauma
|
||||
|
||||
GUILayoutGroup priceLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), footerLayout.RectTransform), isHorizontal: true);
|
||||
GUITextBlock priceLabelBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), priceLayout.RectTransform), TextManager.Get("campaignstore.total"));
|
||||
GUITextBlock priceBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), priceLayout.RectTransform), UpgradeStore.FormatCurrency(medicalClinic.GetTotalCost()), font: GUI.SubHeadingFont,
|
||||
GUITextBlock priceBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), priceLayout.RectTransform), TextManager.FormatCurrency(medicalClinic.GetTotalCost()), font: GUIStyle.SubHeadingFont,
|
||||
textAlignment: Alignment.Right);
|
||||
|
||||
GUILayoutGroup buttonLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), footerLayout.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterRight);
|
||||
GUIButton healButton = new GUIButton(new RectTransform(new Vector2(0.33f, 1f), buttonLayout.RectTransform), TextManager.Get("medicalclinic.heal"))
|
||||
{
|
||||
Enabled = medicalClinic.PendingHeals.Any() && medicalClinic.GetTotalCost() < medicalClinic.GetMoney(),
|
||||
Enabled = medicalClinic.PendingHeals.Any() && medicalClinic.GetWallet().CanAfford(medicalClinic.GetTotalCost()),
|
||||
OnClicked = (button, _) =>
|
||||
{
|
||||
button.Enabled = false;
|
||||
@@ -679,12 +679,12 @@ namespace Barotrauma
|
||||
|
||||
GUILayoutGroup textLayout = new GUILayoutGroup(new RectTransform(Vector2.One, parentLayout.RectTransform), isHorizontal: true);
|
||||
|
||||
string name = prefab.Name;
|
||||
LocalizedString name = prefab.Name;
|
||||
|
||||
GUIFrame textContainer = new GUIFrame(new RectTransform(new Vector2(0.6f, 1f), textLayout.RectTransform), style: null);
|
||||
GUITextBlock afflictionName = new GUITextBlock(new RectTransform(Vector2.One, textContainer.RectTransform), name, font: GUI.SubHeadingFont);
|
||||
GUITextBlock afflictionName = new GUITextBlock(new RectTransform(Vector2.One, textContainer.RectTransform), name, font: GUIStyle.SubHeadingFont);
|
||||
|
||||
GUITextBlock healCost = new GUITextBlock(new RectTransform(new Vector2(0.2f, 1f), textLayout.RectTransform), UpgradeStore.FormatCurrency(affliction.Price), textAlignment: Alignment.Center, font: GUI.LargeFont)
|
||||
GUITextBlock healCost = new GUITextBlock(new RectTransform(new Vector2(0.2f, 1f), textLayout.RectTransform), TextManager.FormatCurrency(affliction.Price), textAlignment: Alignment.Center, font: GUIStyle.LargeFont)
|
||||
{
|
||||
Padding = Vector4.Zero
|
||||
};
|
||||
@@ -702,7 +702,7 @@ namespace Barotrauma
|
||||
}
|
||||
};
|
||||
|
||||
EnsureTextDoesntOverflow(name, afflictionName, textContainer.Rect, ImmutableArray.Create(textLayout, parentLayout));
|
||||
EnsureTextDoesntOverflow(name.Value, afflictionName, textContainer.Rect, ImmutableArray.Create(textLayout, parentLayout));
|
||||
|
||||
healElement.Afflictions.Add(new PendingAfflictionElement(affliction, backgroundFrame, healCost));
|
||||
|
||||
@@ -720,8 +720,8 @@ namespace Barotrauma
|
||||
|
||||
GUILayoutGroup textGroup = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.8f), parent.RectTransform));
|
||||
|
||||
string? characterName = info.Name,
|
||||
jobName = null;
|
||||
string? characterName = info.Name;
|
||||
LocalizedString? jobName = null;
|
||||
|
||||
GUITextBlock? nameBlock = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), textGroup.RectTransform), characterName),
|
||||
jobBlock = null;
|
||||
@@ -741,7 +741,7 @@ namespace Barotrauma
|
||||
|
||||
if (jobBlock is null) { return; }
|
||||
|
||||
EnsureTextDoesntOverflow(jobName, jobBlock, parent.Rect, layoutGroups);
|
||||
EnsureTextDoesntOverflow(jobName?.Value, jobBlock, parent.Rect, layoutGroups);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -766,14 +766,14 @@ namespace Barotrauma
|
||||
mainFrame.RectTransform.ScreenSpaceOffset = new Point((int)location.X, GameMain.GraphicsHeight - mainFrame.Rect.Height);
|
||||
}
|
||||
|
||||
GUITextBlock feedbackBlock = new GUITextBlock(new RectTransform(Vector2.One, mainFrame.RectTransform), TextManager.Get("pleasewaitupnp"), textAlignment: Alignment.Center, font: GUI.LargeFont, wrap: true)
|
||||
GUITextBlock feedbackBlock = new GUITextBlock(new RectTransform(Vector2.One, mainFrame.RectTransform), TextManager.Get("pleasewaitupnp"), textAlignment: Alignment.Center, font: GUIStyle.LargeFont, wrap: true)
|
||||
{
|
||||
Visible = true
|
||||
};
|
||||
|
||||
GUIButton treatAllButton = new GUIButton(new RectTransform(new Vector2(1f, 0.2f), mainLayout.RectTransform), TextManager.Get("medicalclinic.treatall"))
|
||||
{
|
||||
Font = GUI.SubHeadingFont,
|
||||
Font = GUIStyle.SubHeadingFont,
|
||||
Visible = false
|
||||
};
|
||||
|
||||
@@ -793,7 +793,7 @@ namespace Barotrauma
|
||||
if (request.Result != MedicalClinic.RequestResult.Success)
|
||||
{
|
||||
feedbackBlock.Text = GetErrorText(request.Result);
|
||||
feedbackBlock.TextColor = GUI.Style.Red;
|
||||
feedbackBlock.TextColor = GUIStyle.Red;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -844,11 +844,11 @@ namespace Barotrauma
|
||||
|
||||
GUILayoutGroup topTextLayout = new GUILayoutGroup(new RectTransform(Vector2.One, topLayout.RectTransform), isHorizontal: true);
|
||||
|
||||
GUITextBlock prefabBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), topTextLayout.RectTransform), prefab.Name, font: GUI.SubHeadingFont);
|
||||
GUITextBlock prefabBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), topTextLayout.RectTransform), prefab.Name, font: GUIStyle.SubHeadingFont);
|
||||
|
||||
Color textColor = Color.Lerp(GUI.Style.Orange, GUI.Style.Red, (int)affliction.AfflictionSeverity / 2f);
|
||||
Color textColor = Color.Lerp(GUIStyle.Orange, GUIStyle.Red, (int)affliction.AfflictionSeverity / 2f);
|
||||
|
||||
string vitalityText = TextManager.GetWithVariable("medicalclinic.vitalitydifference", "[amount]", (-affliction.Strength).ToString());
|
||||
LocalizedString vitalityText = TextManager.GetWithVariable("medicalclinic.vitalitydifference", "[amount]", (-affliction.Strength).ToString());
|
||||
GUITextBlock vitalityBlock = new GUITextBlock(new RectTransform(new Vector2(0.25f, 1f), topTextLayout.RectTransform), vitalityText, textAlignment: Alignment.Center)
|
||||
{
|
||||
TextColor = textColor,
|
||||
@@ -857,8 +857,8 @@ namespace Barotrauma
|
||||
AutoScaleHorizontal = true
|
||||
};
|
||||
|
||||
string severityText = TextManager.Get($"AfflictionStrength{affliction.AfflictionSeverity}");
|
||||
GUITextBlock severityBlock = new GUITextBlock(new RectTransform(new Vector2(0.25f, 1f), topTextLayout.RectTransform), severityText, textAlignment: Alignment.Center, font: GUI.SubHeadingFont)
|
||||
LocalizedString severityText = TextManager.Get($"AfflictionStrength{affliction.AfflictionSeverity}");
|
||||
GUITextBlock severityBlock = new GUITextBlock(new RectTransform(new Vector2(0.25f, 1f), topTextLayout.RectTransform), severityText, textAlignment: Alignment.Center, font: GUIStyle.SubHeadingFont)
|
||||
{
|
||||
TextColor = textColor,
|
||||
DisabledTextColor = textColor * 0.5f,
|
||||
@@ -866,17 +866,17 @@ namespace Barotrauma
|
||||
AutoScaleHorizontal = true
|
||||
};
|
||||
|
||||
EnsureTextDoesntOverflow(prefab.Name, prefabBlock, prefabBlock.Rect, ImmutableArray.Create(mainLayout, topLayout, topTextLayout));
|
||||
EnsureTextDoesntOverflow(prefab.Name.Value, prefabBlock, prefabBlock.Rect, ImmutableArray.Create(mainLayout, topLayout, topTextLayout));
|
||||
|
||||
GUILayoutGroup bottomLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.66f), mainLayout.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft);
|
||||
|
||||
GUILayoutGroup bottomTextLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 1f), bottomLayout.RectTransform));
|
||||
GUITextBlock descriptionBlock = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), bottomTextLayout.RectTransform), ToolBox.LimitString(prefab.Description, GUI.IntScale(64)), wrap: true)
|
||||
GUITextBlock descriptionBlock = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), bottomTextLayout.RectTransform), ToolBox.LimitString(prefab.Description, GUIStyle.Font, GUI.IntScale(64)), wrap: true)
|
||||
{
|
||||
ToolTip = prefab.Description
|
||||
};
|
||||
|
||||
GUITextBlock priceBlock = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), bottomTextLayout.RectTransform), UpgradeStore.FormatCurrency(affliction.Price), font: GUI.LargeFont);
|
||||
GUITextBlock priceBlock = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), bottomTextLayout.RectTransform), TextManager.FormatCurrency(affliction.Price), font: GUIStyle.LargeFont);
|
||||
|
||||
GUIButton buyButton = new GUIButton(new RectTransform(new Vector2(0.2f, 0.75f), bottomLayout.RectTransform), style: "CrewManagementAddButton");
|
||||
|
||||
@@ -931,7 +931,7 @@ namespace Barotrauma
|
||||
});
|
||||
}
|
||||
|
||||
private static void EnsureTextDoesntOverflow(string? text, GUITextBlock textBlock, Rectangle bounds, ImmutableArray<GUILayoutGroup>? layoutGroups = null)
|
||||
public static void EnsureTextDoesntOverflow(string? text, GUITextBlock textBlock, Rectangle bounds, ImmutableArray<GUILayoutGroup>? layoutGroups = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(text)) { return; }
|
||||
|
||||
@@ -968,7 +968,7 @@ namespace Barotrauma
|
||||
if (GameMain.IsSingleplayer || !(pendingHealList is { ErrorBlock: { } errorBlock, HealList: { } healList })) { return; }
|
||||
|
||||
errorBlock.Visible = true;
|
||||
errorBlock.TextColor = GUI.Style.TextColor;
|
||||
errorBlock.TextColor = GUIStyle.TextColorNormal;
|
||||
errorBlock.Text = TextManager.Get("pleasewaitupnp");
|
||||
healList.Visible = false;
|
||||
|
||||
@@ -983,7 +983,7 @@ namespace Barotrauma
|
||||
if (request.Result != MedicalClinic.RequestResult.Success)
|
||||
{
|
||||
errorBlock.Text = GetErrorText(request.Result);
|
||||
errorBlock.TextColor = GUI.Style.Red;
|
||||
errorBlock.TextColor = GUIStyle.Red;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1011,7 +1011,7 @@ namespace Barotrauma
|
||||
selectedCrewAfflictionList = null;
|
||||
}
|
||||
|
||||
private static string GetErrorText(MedicalClinic.RequestResult result)
|
||||
private static LocalizedString GetErrorText(MedicalClinic.RequestResult result)
|
||||
{
|
||||
return result switch
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -31,19 +31,12 @@ namespace Barotrauma
|
||||
private readonly List<SubmarineInfo> subsToShow;
|
||||
private readonly SubmarineDisplayContent[] submarineDisplays = new SubmarineDisplayContent[submarinesPerPage];
|
||||
private SubmarineInfo selectedSubmarine = null;
|
||||
private string purchaseAndSwitchText, purchaseOnlyText, deliveryText, currentSubText, deliveryFeeText, priceText, switchText, missingPreviewText, currencyShorthandText, currencyLongText;
|
||||
private LocalizedString purchaseAndSwitchText, purchaseOnlyText, deliveryText, currentSubText, deliveryFeeText, priceText, switchText, missingPreviewText, currencyName;
|
||||
private readonly RectTransform parent;
|
||||
private readonly Action closeAction;
|
||||
private Sprite pageIndicator;
|
||||
|
||||
public static readonly string[] DeliveryTextVariables = new string[] { "[submarinename1]", "[location1]", "[location2]", "[submarinename2]", "[amount]", "[currencyname]" };
|
||||
public static readonly string[] SwitchTextVariables = new string[] { "[submarinename1]", "[submarinename2]" };
|
||||
public static readonly string[] PurchaseAndSwitchTextVariables = new string[] { "[submarinename1]", "[amount]", "[currencyname]", "[submarinename2]" };
|
||||
public static readonly string[] PurchaseTextVariables = new string[] { "[submarinename]", "[amount]", "[currencyname]" };
|
||||
|
||||
private static readonly string[] notEnoughCreditsDeliveryTextVariables = new string[] { "[currencyname]", "[submarinename]", "[location1]", "[location2]" };
|
||||
private static readonly string[] notEnoughCreditsPurchaseTextVariables = new string[] { "[currencyname]", "[submarinename]" };
|
||||
private readonly string[] messageBoxOptions;
|
||||
private readonly LocalizedString[] messageBoxOptions;
|
||||
|
||||
public const int DeliveryFeePerDistanceTravelled = 1000;
|
||||
public static bool ContentRefreshRequired = false;
|
||||
@@ -77,11 +70,11 @@ namespace Barotrauma
|
||||
|
||||
if (GameMain.Client == null)
|
||||
{
|
||||
messageBoxOptions = new string[2] { TextManager.Get("Yes"), TextManager.Get("Cancel") };
|
||||
messageBoxOptions = new LocalizedString[2] { TextManager.Get("Yes"), TextManager.Get("Cancel") };
|
||||
}
|
||||
else
|
||||
{
|
||||
messageBoxOptions = new string[2] { TextManager.Get("Yes") + " " + TextManager.Get("initiatevoting"), TextManager.Get("Cancel") };
|
||||
messageBoxOptions = new LocalizedString[2] { TextManager.Get("Yes") + " " + TextManager.Get("initiatevoting"), TextManager.Get("Cancel") };
|
||||
}
|
||||
|
||||
if (Submarine.MainSub?.Info == null) { return; }
|
||||
@@ -91,23 +84,19 @@ namespace Barotrauma
|
||||
private void Initialize()
|
||||
{
|
||||
initialized = true;
|
||||
currentSubText = TextManager.Get("currentsub");
|
||||
deliveryFeeText = TextManager.Get("deliveryfee");
|
||||
deliveryText = TextManager.Get("requestdeliverybutton");
|
||||
switchText = TextManager.Get("switchtosubmarinebutton");
|
||||
purchaseAndSwitchText = TextManager.Get("purchaseandswitch");
|
||||
purchaseOnlyText = TextManager.Get("purchase");
|
||||
priceText = TextManager.Get("price");
|
||||
if (transferService)
|
||||
{
|
||||
deliveryFee = CalculateDeliveryFee();
|
||||
currentSubText = TextManager.Get("currentsub");
|
||||
deliveryFeeText = TextManager.Get("deliveryfee");
|
||||
deliveryText = TextManager.Get("requestdeliverybutton");
|
||||
switchText = TextManager.Get("switchtosubmarinebutton");
|
||||
}
|
||||
else
|
||||
{
|
||||
purchaseAndSwitchText = TextManager.Get("purchaseandswitch");
|
||||
purchaseOnlyText = TextManager.Get("purchase");
|
||||
priceText = TextManager.Get("price");
|
||||
}
|
||||
|
||||
currencyShorthandText = TextManager.Get("currencyformat");
|
||||
currencyLongText = TextManager.Get("credit").ToLower();
|
||||
currencyName = TextManager.Get("credit").Value.ToLowerInvariant();
|
||||
|
||||
UpdateSubmarines();
|
||||
missingPreviewText = TextManager.Get("SubPreviewImageNotFound");
|
||||
@@ -135,9 +124,9 @@ namespace Barotrauma
|
||||
};
|
||||
|
||||
content = new GUILayoutGroup(new RectTransform(new Point(background.Rect.Width - HUDLayoutSettings.Padding * 4, background.Rect.Height - HUDLayoutSettings.Padding * 4), background.RectTransform, Anchor.Center)) { AbsoluteSpacing = (int)(HUDLayoutSettings.Padding * 1.5f) };
|
||||
GUITextBlock header = new GUITextBlock(new RectTransform(new Vector2(1f, 0.0f), content.RectTransform), transferService ? TextManager.Get("switchsubmarineheader") : TextManager.GetWithVariable("outpostshipyard", "[location]", GameMain.GameSession.Map.CurrentLocation.Name), font: GUI.LargeFont);
|
||||
GUITextBlock header = new GUITextBlock(new RectTransform(new Vector2(1f, 0.0f), content.RectTransform), transferService ? TextManager.Get("switchsubmarineheader") : TextManager.GetWithVariable("outpostshipyard", "[location]", GameMain.GameSession.Map.CurrentLocation.Name), font: GUIStyle.LargeFont);
|
||||
header.CalculateHeightFromText(0, true);
|
||||
GUITextBlock credits = new GUITextBlock(new RectTransform(Vector2.One, header.RectTransform), "", font: GUI.SubHeadingFont, textAlignment: Alignment.CenterRight)
|
||||
GUITextBlock credits = new GUITextBlock(new RectTransform(Vector2.One, header.RectTransform), "", font: GUIStyle.SubHeadingFont, textAlignment: Alignment.CenterRight)
|
||||
{
|
||||
TextGetter = CampaignUI.GetMoney
|
||||
};
|
||||
@@ -159,7 +148,7 @@ namespace Barotrauma
|
||||
specsFrame = new GUIListBox(new RectTransform(new Vector2(0.39f, 1f), infoFrame.RectTransform), style: null) { Spacing = GUI.IntScale(5), Padding = new Vector4(HUDLayoutSettings.Padding / 2f, HUDLayoutSettings.Padding, 0, 0) };
|
||||
new GUIFrame(new RectTransform(new Vector2(0.02f, 0.8f), infoFrame.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.1f) }, style: "VerticalLine");
|
||||
GUIListBox descriptionFrame = new GUIListBox(new RectTransform(new Vector2(0.59f, 1f), infoFrame.RectTransform), style: null) { Padding = new Vector4(HUDLayoutSettings.Padding / 2f, HUDLayoutSettings.Padding * 1.5f, HUDLayoutSettings.Padding * 1.5f, HUDLayoutSettings.Padding / 2f) };
|
||||
descriptionTextBlock = new GUITextBlock(new RectTransform(new Vector2(1, 0), descriptionFrame.Content.RectTransform), string.Empty, font: GUI.Font, wrap: true) { CanBeFocused = false };
|
||||
descriptionTextBlock = new GUITextBlock(new RectTransform(new Vector2(1, 0), descriptionFrame.Content.RectTransform), string.Empty, font: GUIStyle.Font, wrap: true) { CanBeFocused = false };
|
||||
|
||||
GUILayoutGroup buttonFrame = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.075f), content.RectTransform), childAnchor: Anchor.CenterRight) { IsHorizontal = true, AbsoluteSpacing = HUDLayoutSettings.Padding };
|
||||
|
||||
@@ -180,7 +169,7 @@ namespace Barotrauma
|
||||
SetConfirmButtonState(false);
|
||||
|
||||
pageIndicatorHolder = new GUIFrame(new RectTransform(new Vector2(1f, 1.5f), submarineControlsGroup.RectTransform), style: null);
|
||||
pageIndicator = GUI.Style.GetComponentStyle("GUIPageIndicator").GetDefaultSprite();
|
||||
pageIndicator = GUIStyle.GetComponentStyle("GUIPageIndicator").GetDefaultSprite();
|
||||
UpdatePaging();
|
||||
|
||||
for (int i = 0; i < submarineDisplays.Length; i++)
|
||||
@@ -191,9 +180,9 @@ namespace Barotrauma
|
||||
};
|
||||
submarineDisplayElement.submarineImage = new GUIImage(new RectTransform(new Vector2(0.8f, 1f), submarineDisplayElement.background.RectTransform, Anchor.Center), null, true);
|
||||
submarineDisplayElement.middleTextBlock = new GUITextBlock(new RectTransform(new Vector2(0.8f, 1f), submarineDisplayElement.background.RectTransform, Anchor.Center), string.Empty, textAlignment: Alignment.Center);
|
||||
submarineDisplayElement.submarineName = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding) }, string.Empty, textAlignment: Alignment.Center, font: GUI.SubHeadingFont);
|
||||
submarineDisplayElement.submarineClass = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding + (int)GUI.Font.MeasureString(submarineDisplayElement.submarineName.Text).Y) }, string.Empty, textAlignment: Alignment.Center);
|
||||
submarineDisplayElement.submarineFee = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.BottomCenter, Pivot.BottomCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding) }, string.Empty, textAlignment: Alignment.Center, font: GUI.SubHeadingFont);
|
||||
submarineDisplayElement.submarineName = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding) }, string.Empty, textAlignment: Alignment.Center, font: GUIStyle.SubHeadingFont);
|
||||
submarineDisplayElement.submarineClass = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding + (int)GUIStyle.Font.MeasureString(submarineDisplayElement.submarineName.Text).Y) }, string.Empty, textAlignment: Alignment.Center);
|
||||
submarineDisplayElement.submarineFee = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.BottomCenter, Pivot.BottomCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding) }, string.Empty, textAlignment: Alignment.Center, font: GUIStyle.SubHeadingFont);
|
||||
submarineDisplayElement.selectSubmarineButton = new GUIButton(new RectTransform(Vector2.One, submarineDisplayElement.background.RectTransform), style: null);
|
||||
submarineDisplayElement.previewButton = new GUIButton(new RectTransform(Vector2.One * 0.12f, submarineDisplayElement.background.RectTransform, anchor: Anchor.BottomRight, pivot: Pivot.BottomRight, scaleBasis: ScaleBasis.BothHeight) { AbsoluteOffset = new Point((int)(0.03f * background.Rect.Height)) }, style: "ExpandButton")
|
||||
{
|
||||
@@ -342,7 +331,7 @@ namespace Barotrauma
|
||||
|
||||
if (!GameMain.GameSession.IsSubmarineOwned(subToDisplay))
|
||||
{
|
||||
string amountString = currencyShorthandText.Replace("[credits]", subToDisplay.Price.ToString());
|
||||
LocalizedString amountString = TextManager.FormatCurrency(subToDisplay.Price);
|
||||
submarineDisplays[i].submarineFee.Text = priceText.Replace("[amount]", amountString).Replace("[currencyname]", string.Empty).TrimEnd();
|
||||
}
|
||||
else
|
||||
@@ -351,7 +340,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (deliveryFee > 0)
|
||||
{
|
||||
string amountString = currencyShorthandText.Replace("[credits]", deliveryFee.ToString());
|
||||
LocalizedString amountString = TextManager.FormatCurrency(deliveryFee);
|
||||
submarineDisplays[i].submarineFee.Text = deliveryFeeText.Replace("[amount]", amountString).Replace("[currencyname]", string.Empty).TrimEnd();
|
||||
}
|
||||
else
|
||||
@@ -535,7 +524,7 @@ namespace Barotrauma
|
||||
listBackground.Sprite = previewImage;
|
||||
listBackground.SetCrop(true);
|
||||
|
||||
ScalableFont font = GUI.Font;
|
||||
GUIFont font = GUIStyle.Font;
|
||||
info.CreateSpecsWindow(specsFrame, font);
|
||||
descriptionTextBlock.Text = info.Description;
|
||||
descriptionTextBlock.CalculateHeightFromText();
|
||||
@@ -588,10 +577,13 @@ namespace Barotrauma
|
||||
|
||||
private void ShowTransferPrompt()
|
||||
{
|
||||
if (GameMain.GameSession.Campaign.Money < deliveryFee && deliveryFee > 0)
|
||||
if (!GameMain.GameSession.Campaign.Wallet.CanAfford(deliveryFee) && deliveryFee > 0)
|
||||
{
|
||||
new GUIMessageBox(TextManager.Get("deliveryrequestheader"), TextManager.GetWithVariables("notenoughmoneyfordeliverytext", notEnoughCreditsDeliveryTextVariables,
|
||||
new string[] { currencyLongText, selectedSubmarine.DisplayName, deliveryLocationName, GameMain.GameSession.Map.CurrentLocation.Name }));
|
||||
new GUIMessageBox(TextManager.Get("deliveryrequestheader"), TextManager.GetWithVariables("notenoughmoneyfordeliverytext",
|
||||
("[currencyname]", currencyName),
|
||||
("[submarinename]", selectedSubmarine.DisplayName),
|
||||
("[location1]", deliveryLocationName),
|
||||
("[location2]", GameMain.GameSession.Map.CurrentLocation.Name)));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -599,13 +591,19 @@ namespace Barotrauma
|
||||
|
||||
if (deliveryFee > 0)
|
||||
{
|
||||
msgBox = new GUIMessageBox(TextManager.Get("deliveryrequestheader"), TextManager.GetWithVariables("deliveryrequesttext", DeliveryTextVariables,
|
||||
new string[6] { selectedSubmarine.DisplayName, deliveryLocationName, GameMain.GameSession.Map.CurrentLocation.Name, CurrentOrPendingSubmarine().DisplayName, deliveryFee.ToString(), currencyLongText }), messageBoxOptions);
|
||||
msgBox = new GUIMessageBox(TextManager.Get("deliveryrequestheader"), TextManager.GetWithVariables("deliveryrequesttext",
|
||||
("[submarinename1]", selectedSubmarine.DisplayName),
|
||||
("[location1]", deliveryLocationName),
|
||||
("[location2]", GameMain.GameSession.Map.CurrentLocation.Name),
|
||||
("[submarinename2]", CurrentOrPendingSubmarine().DisplayName),
|
||||
("[amount]", deliveryFee.ToString()),
|
||||
("[currencyname]", currencyName)), messageBoxOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
msgBox = new GUIMessageBox(TextManager.Get("switchsubmarineheader"), TextManager.GetWithVariables("switchsubmarinetext", SwitchTextVariables,
|
||||
new string[2] { CurrentOrPendingSubmarine().DisplayName, selectedSubmarine.DisplayName }), messageBoxOptions);
|
||||
msgBox = new GUIMessageBox(TextManager.Get("switchsubmarineheader"), TextManager.GetWithVariables("switchsubmarinetext",
|
||||
("[submarinename1]", CurrentOrPendingSubmarine().DisplayName),
|
||||
("[submarinename2]", selectedSubmarine.DisplayName)), messageBoxOptions);
|
||||
}
|
||||
|
||||
msgBox.Buttons[0].OnClicked = (applyButton, obj) =>
|
||||
@@ -627,10 +625,11 @@ namespace Barotrauma
|
||||
|
||||
private void ShowBuyPrompt(bool purchaseOnly)
|
||||
{
|
||||
if (GameMain.GameSession.Campaign.Money < selectedSubmarine.Price)
|
||||
if (!GameMain.GameSession.Campaign.Wallet.CanAfford(selectedSubmarine.Price))
|
||||
{
|
||||
new GUIMessageBox(TextManager.Get("purchasesubmarineheader"), TextManager.GetWithVariables("notenoughmoneyforpurchasetext", notEnoughCreditsPurchaseTextVariables,
|
||||
new string[2] { currencyLongText, selectedSubmarine.DisplayName }));
|
||||
new GUIMessageBox(TextManager.Get("purchasesubmarineheader"), TextManager.GetWithVariables("notenoughmoneyforpurchasetext",
|
||||
("[currencyname]", currencyName),
|
||||
("[submarinename]", selectedSubmarine.DisplayName)));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -638,8 +637,11 @@ namespace Barotrauma
|
||||
|
||||
if (!purchaseOnly)
|
||||
{
|
||||
msgBox = new GUIMessageBox(TextManager.Get("purchaseandswitchsubmarineheader"), TextManager.GetWithVariables("purchaseandswitchsubmarinetext", PurchaseAndSwitchTextVariables,
|
||||
new string[4] { selectedSubmarine.DisplayName, selectedSubmarine.Price.ToString(), currencyLongText, CurrentOrPendingSubmarine().DisplayName }), messageBoxOptions);
|
||||
msgBox = new GUIMessageBox(TextManager.Get("purchaseandswitchsubmarineheader"), TextManager.GetWithVariables("purchaseandswitchsubmarinetext",
|
||||
("[submarinename1]", selectedSubmarine.DisplayName),
|
||||
("[amount]", selectedSubmarine.Price.ToString()),
|
||||
("[currencyname]", currencyName),
|
||||
("[submarinename2]", CurrentOrPendingSubmarine().DisplayName)), messageBoxOptions);
|
||||
|
||||
msgBox.Buttons[0].OnClicked = (applyButton, obj) =>
|
||||
{
|
||||
@@ -658,8 +660,10 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
msgBox = new GUIMessageBox(TextManager.Get("purchasesubmarineheader"), TextManager.GetWithVariables("purchasesubmarinetext", PurchaseTextVariables,
|
||||
new string[3] { selectedSubmarine.DisplayName, selectedSubmarine.Price.ToString(), currencyLongText }), messageBoxOptions);
|
||||
msgBox = new GUIMessageBox(TextManager.Get("purchasesubmarineheader"), TextManager.GetWithVariables("purchasesubmarinetext",
|
||||
("[submarinename]", selectedSubmarine.DisplayName),
|
||||
("[amount]", selectedSubmarine.Price.ToString()),
|
||||
("[currencyname]", currencyName)), messageBoxOptions);
|
||||
|
||||
msgBox.Buttons[0].OnClicked = (applyButton, obj) =>
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -19,11 +19,7 @@ namespace Barotrauma
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool Slice
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public bool Slice => Slices != null;
|
||||
|
||||
public Rectangle[] Slices
|
||||
{
|
||||
@@ -54,7 +50,7 @@ namespace Barotrauma
|
||||
|
||||
public TransitionMode TransitionMode { get; private set; }
|
||||
|
||||
public UISprite(XElement element)
|
||||
public UISprite(ContentXElement element)
|
||||
{
|
||||
Sprite = new Sprite(element);
|
||||
MaintainAspectRatio = element.GetAttributeBool("maintainaspectratio", false);
|
||||
@@ -69,6 +65,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
Vector4 sliceVec = element.GetAttributeVector4("slice", Vector4.Zero);
|
||||
Slices = null;
|
||||
if (sliceVec != Vector4.Zero)
|
||||
{
|
||||
minBorderScale = element.GetAttributeFloat("minborderscale", 0.1f);
|
||||
@@ -76,7 +73,6 @@ namespace Barotrauma
|
||||
|
||||
Rectangle slice = new Rectangle((int)sliceVec.X, (int)sliceVec.Y, (int)(sliceVec.Z - sliceVec.X), (int)(sliceVec.W - sliceVec.Y));
|
||||
|
||||
Slice = true;
|
||||
Slices = new Rectangle[9];
|
||||
|
||||
//top-left
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Barotrauma
|
||||
|
||||
private readonly CampaignUI campaignUI;
|
||||
private CampaignMode? Campaign => campaignUI.Campaign;
|
||||
private int AvailableMoney => Campaign?.Money ?? 0;
|
||||
private Wallet PlayerWallet => Campaign?.Wallet ?? Wallet.Invalid;
|
||||
private UpgradeTab selectedUpgradeTab = UpgradeTab.Upgrade;
|
||||
|
||||
private GUIMessageBox? currectConfirmation;
|
||||
@@ -61,7 +61,7 @@ namespace Barotrauma
|
||||
private Vector2[][] subHullVertices = new Vector2[0][];
|
||||
private List<Structure> submarineWalls = new List<Structure>();
|
||||
|
||||
public MapEntity? HoveredItem;
|
||||
public MapEntity? HoveredEntity;
|
||||
private bool highlightWalls;
|
||||
|
||||
private UpgradeCategory? currentUpgradeCategory;
|
||||
@@ -73,6 +73,8 @@ namespace Barotrauma
|
||||
|
||||
private Point screenResolution;
|
||||
|
||||
private bool needsRefresh = true;
|
||||
|
||||
/// <summary>
|
||||
/// While set to true any call to <see cref="RefreshUpgradeList"/> will cause the buy button to be disabled and to not update the prices.
|
||||
/// This is to prevent us from buying another upgrade before the server has given us the new prices and causing potential syncing issues.
|
||||
@@ -102,12 +104,18 @@ namespace Barotrauma
|
||||
CreateUI(upgradeFrame);
|
||||
|
||||
if (Campaign == null) { return; }
|
||||
Campaign.UpgradeManager.OnUpgradesChanged += RefreshAll;
|
||||
Campaign.CargoManager.OnPurchasedItemsChanged += RefreshAll;
|
||||
Campaign.CargoManager.OnSoldItemsChanged += RefreshAll;
|
||||
Campaign.UpgradeManager.OnUpgradesChanged += RequestRefresh;
|
||||
Campaign.CargoManager.OnPurchasedItemsChanged += RequestRefresh;
|
||||
Campaign.CargoManager.OnSoldItemsChanged += RequestRefresh;
|
||||
Campaign.OnMoneyChanged.RegisterOverwriteExisting(nameof(UpgradeStore).ToIdentifier(), e => { RequestRefresh(); } );
|
||||
}
|
||||
|
||||
public void RefreshAll()
|
||||
public void RequestRefresh()
|
||||
{
|
||||
needsRefresh = true;
|
||||
}
|
||||
|
||||
private void RefreshAll()
|
||||
{
|
||||
switch (selectedUpgradeTab)
|
||||
{
|
||||
@@ -130,6 +138,7 @@ namespace Barotrauma
|
||||
}
|
||||
break;
|
||||
}
|
||||
needsRefresh = false;
|
||||
}
|
||||
|
||||
private void RefreshUpgradeList()
|
||||
@@ -184,7 +193,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
// reset the order first
|
||||
foreach (UpgradeCategory category in UpgradeCategory.Categories)
|
||||
foreach (UpgradeCategory category in UpgradeCategory.Categories.OrderBy(c => c.Name))
|
||||
{
|
||||
GUIComponent component = categoryList.Content.FindChild(c => c.UserData is CategoryData categoryData && categoryData.Category == category);
|
||||
component?.SetAsLastChild();
|
||||
@@ -245,7 +254,7 @@ namespace Barotrauma
|
||||
* |----------------------------|
|
||||
*/
|
||||
GUILayoutGroup tooltipLayout = new GUILayoutGroup(rectT(0.95f,0.95f, ItemInfoFrame, Anchor.Center)) { Stretch = true };
|
||||
new GUITextBlock(rectT(1, 0, tooltipLayout), string.Empty, font: GUI.SubHeadingFont) { UserData = "itemname" };
|
||||
new GUITextBlock(rectT(1, 0, tooltipLayout), string.Empty, font: GUIStyle.SubHeadingFont) { UserData = "itemname" };
|
||||
new GUITextBlock(rectT(1, 0, tooltipLayout), TextManager.Get("UpgradeUITooltip.UpgradeListHeader"));
|
||||
new GUIListBox(rectT(1, 0.5f, tooltipLayout), style: null) { ScrollBarVisible = false, AutoHideScrollBar = false, SmoothScroll = true, UserData = "upgradelist"};
|
||||
new GUITextBlock(rectT(1, 0, tooltipLayout), string.Empty) { UserData = "moreindicator" };
|
||||
@@ -268,7 +277,7 @@ namespace Barotrauma
|
||||
GUILayoutGroup leftLayout = new GUILayoutGroup(rectT(0.5f, 1, topHeaderLayout)) { RelativeSpacing = 0.05f };
|
||||
GUILayoutGroup locationLayout = new GUILayoutGroup(rectT(1, 0.5f, leftLayout), isHorizontal: true);
|
||||
GUIImage submarineIcon = new GUIImage(rectT(new Point(locationLayout.Rect.Height, locationLayout.Rect.Height), locationLayout), style: "SubmarineIcon", scaleToFit: true);
|
||||
new GUITextBlock(rectT(1.0f - submarineIcon.RectTransform.RelativeSize.X, 1, locationLayout), TextManager.Get("UpgradeUI.Title"), font: GUI.LargeFont);
|
||||
new GUITextBlock(rectT(1.0f - submarineIcon.RectTransform.RelativeSize.X, 1, locationLayout), TextManager.Get("UpgradeUI.Title"), font: GUIStyle.LargeFont);
|
||||
categoryButtonLayout = new GUILayoutGroup(rectT(0.4f, 0.3f, leftLayout), isHorizontal: true) { Stretch = true };
|
||||
GUIButton upgradeButton = new GUIButton(rectT(1, 1f, categoryButtonLayout), TextManager.Get("UICategory.Upgrades"), style: "GUITabButton") { UserData = UpgradeTab.Upgrade, Selected = selectedUpgradeTab == UpgradeTab.Upgrade };
|
||||
GUIButton repairButton = new GUIButton(rectT(1, 1f, categoryButtonLayout), TextManager.Get("UICategory.Maintenance"), style: "GUITabButton") { UserData = UpgradeTab.Repairs, Selected = selectedUpgradeTab == UpgradeTab.Repairs };
|
||||
@@ -285,9 +294,9 @@ namespace Barotrauma
|
||||
*/
|
||||
GUILayoutGroup rightLayout = new GUILayoutGroup(rectT(0.5f, 1, topHeaderLayout), childAnchor: Anchor.TopRight);
|
||||
GUILayoutGroup priceLayout = new GUILayoutGroup(rectT(1, 0.8f, rightLayout), childAnchor: Anchor.Center) { RelativeSpacing = 0.08f };
|
||||
new GUITextBlock(rectT(1f, 0f, priceLayout), TextManager.Get("CampaignStore.Balance"), font: GUI.SubHeadingFont, textAlignment: Alignment.Right);
|
||||
new GUITextBlock(rectT(1f, 0f, priceLayout), FormatCurrency(AvailableMoney, format: true), font: GUI.SubHeadingFont, textAlignment: Alignment.Right) { TextGetter = () => FormatCurrency(AvailableMoney, format: true) };
|
||||
new GUIFrame(rectT(0.5f, 0.1f, rightLayout, Anchor.BottomRight), style: "HorizontalLine") { IgnoreLayoutGroups = true };
|
||||
new GUITextBlock(rectT(1f, 0f, priceLayout), TextManager.Get("CampaignStore.Balance"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Right);
|
||||
new GUITextBlock(rectT(1f, 0f, priceLayout), TextManager.FormatCurrency(PlayerWallet.Balance), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Right) { TextGetter = () => TextManager.FormatCurrency(PlayerWallet.Balance) };
|
||||
new GUIFrame(rectT(0.5f, 0.1f, rightLayout, Anchor.BottomRight), style: "HorizontalLine") { IgnoreLayoutGroups = true };
|
||||
|
||||
repairButton.OnClicked = upgradeButton.OnClicked = (button, o) =>
|
||||
{
|
||||
@@ -343,15 +352,15 @@ namespace Barotrauma
|
||||
private void DrawItemSwapPreview(SpriteBatch spriteBatch, GUICustomComponent component)
|
||||
{
|
||||
var selectedItem = customizeTabOpen ?
|
||||
activeItemSwapSlideDown?.UserData as Item ?? HoveredItem as Item :
|
||||
HoveredItem as Item;
|
||||
activeItemSwapSlideDown?.UserData as Item ?? HoveredEntity as Item :
|
||||
HoveredEntity as Item;
|
||||
if (selectedItem?.Prefab.SwappableItem == null) { return; }
|
||||
|
||||
Sprite schematicsSprite = selectedItem.Prefab.SwappableItem.SchematicSprite;
|
||||
if (schematicsSprite == null) { return; }
|
||||
float schematicsScale = Math.Min(component.Rect.Width / 2 / schematicsSprite.size.X, component.Rect.Height / schematicsSprite.size.Y);
|
||||
Vector2 center = new Vector2(component.Rect.Center.X, component.Rect.Center.Y);
|
||||
schematicsSprite.Draw(spriteBatch, new Vector2(component.Rect.X, center.Y), GUI.Style.Green, new Vector2(0, schematicsSprite.size.Y / 2),
|
||||
schematicsSprite.Draw(spriteBatch, new Vector2(component.Rect.X, center.Y), GUIStyle.Green, new Vector2(0, schematicsSprite.size.Y / 2),
|
||||
scale: schematicsScale);
|
||||
|
||||
var swappableItemList = selectedUpgradeCategoryLayout?.FindChild("prefablist", true) as GUIListBox;
|
||||
@@ -359,10 +368,10 @@ namespace Barotrauma
|
||||
ItemPrefab swapTo = highlightedElement?.UserData as ItemPrefab ?? selectedItem.PendingItemSwap;
|
||||
if (swapTo?.SwappableItem == null) { return; }
|
||||
Sprite? schematicsSprite2 = swapTo.SwappableItem?.SchematicSprite;
|
||||
schematicsSprite2?.Draw(spriteBatch, new Vector2(component.Rect.Right, center.Y), GUI.Style.Orange, new Vector2(schematicsSprite2.size.X, schematicsSprite2.size.Y / 2),
|
||||
schematicsSprite2?.Draw(spriteBatch, new Vector2(component.Rect.Right, center.Y), GUIStyle.Orange, new Vector2(schematicsSprite2.size.X, schematicsSprite2.size.Y / 2),
|
||||
scale: Math.Min(component.Rect.Width / 2 / schematicsSprite2.size.X, component.Rect.Height / schematicsSprite2.size.Y));
|
||||
|
||||
var arrowSprite = GUI.Style?.GetComponentStyle("GUIButtonToggleRight")?.GetDefaultSprite();
|
||||
var arrowSprite = GUIStyle.GetComponentStyle("GUIButtonToggleRight")?.GetDefaultSprite();
|
||||
if (arrowSprite != null)
|
||||
{
|
||||
arrowSprite.Draw(spriteBatch, center, scale: GUI.Scale);
|
||||
@@ -426,14 +435,14 @@ namespace Barotrauma
|
||||
return false;
|
||||
}
|
||||
|
||||
if (AvailableMoney >= hullRepairCost)
|
||||
if (PlayerWallet.CanAfford(hullRepairCost))
|
||||
{
|
||||
string body = TextManager.GetWithVariable("WallRepairs.PurchasePromptBody", "[amount]", hullRepairCost.ToString());
|
||||
LocalizedString body = TextManager.GetWithVariable("WallRepairs.PurchasePromptBody", "[amount]", hullRepairCost.ToString());
|
||||
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), body, () =>
|
||||
{
|
||||
if (AvailableMoney >= hullRepairCost)
|
||||
if (PlayerWallet.Balance >= hullRepairCost)
|
||||
{
|
||||
Campaign.Money -= hullRepairCost;
|
||||
PlayerWallet.TryDeduct(hullRepairCost);
|
||||
GameAnalyticsManager.AddMoneySpentEvent(hullRepairCost, GameAnalyticsManager.MoneySink.Service, "hullrepairs");
|
||||
Campaign.PurchasedHullRepairs = true;
|
||||
button.Enabled = false;
|
||||
@@ -461,14 +470,14 @@ namespace Barotrauma
|
||||
|
||||
CreateRepairEntry(currentStoreLayout.Content, TextManager.Get("repairallitems"), "RepairItemsButton", itemRepairCost, (button, o) =>
|
||||
{
|
||||
if (AvailableMoney >= itemRepairCost && !Campaign.PurchasedItemRepairs)
|
||||
if (PlayerWallet.Balance >= itemRepairCost && !Campaign.PurchasedItemRepairs)
|
||||
{
|
||||
string body = TextManager.GetWithVariable("ItemRepairs.PurchasePromptBody", "[amount]", itemRepairCost.ToString());
|
||||
LocalizedString body = TextManager.GetWithVariable("ItemRepairs.PurchasePromptBody", "[amount]", itemRepairCost.ToString());
|
||||
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), body, () =>
|
||||
{
|
||||
if (AvailableMoney >= itemRepairCost && !Campaign.PurchasedItemRepairs)
|
||||
if (PlayerWallet.Balance >= itemRepairCost && !Campaign.PurchasedItemRepairs)
|
||||
{
|
||||
Campaign.Money -= itemRepairCost;
|
||||
PlayerWallet.TryDeduct(itemRepairCost);
|
||||
GameAnalyticsManager.AddMoneySpentEvent(hullRepairCost, GameAnalyticsManager.MoneySink.Service, "devicerepairs");
|
||||
Campaign.PurchasedItemRepairs = true;
|
||||
button.Enabled = false;
|
||||
@@ -493,7 +502,7 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (var (item, itemFrame) in itemPreviews)
|
||||
{
|
||||
itemFrame.OutlineColor = itemFrame.Color = isHovered && item.GetComponent<DockingPort>() == null ? GUI.Style.Orange : previewWhite;
|
||||
itemFrame.OutlineColor = itemFrame.Color = isHovered && item.GetComponent<DockingPort>() == null ? GUIStyle.Orange : previewWhite;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
@@ -507,14 +516,14 @@ namespace Barotrauma
|
||||
return false;
|
||||
}
|
||||
|
||||
if (AvailableMoney >= shuttleRetrieveCost && !Campaign.PurchasedLostShuttles)
|
||||
if (PlayerWallet.CanAfford(shuttleRetrieveCost) && !Campaign.PurchasedLostShuttles)
|
||||
{
|
||||
string body = TextManager.GetWithVariable("ReplaceLostShuttles.PurchasePromptBody", "[amount]", shuttleRetrieveCost.ToString());
|
||||
LocalizedString body = TextManager.GetWithVariable("ReplaceLostShuttles.PurchasePromptBody", "[amount]", shuttleRetrieveCost.ToString());
|
||||
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), body, () =>
|
||||
{
|
||||
if (AvailableMoney >= shuttleRetrieveCost && !Campaign.PurchasedLostShuttles)
|
||||
if (PlayerWallet.Balance >= shuttleRetrieveCost && !Campaign.PurchasedLostShuttles)
|
||||
{
|
||||
Campaign.Money -= shuttleRetrieveCost;
|
||||
PlayerWallet.TryDeduct(shuttleRetrieveCost);
|
||||
GameAnalyticsManager.AddMoneySpentEvent(hullRepairCost, GameAnalyticsManager.MoneySink.Service, "retrieveshuttle");
|
||||
Campaign.PurchasedLostShuttles = true;
|
||||
button.Enabled = false;
|
||||
@@ -540,7 +549,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (subInfo.LeftBehindDockingPortIDs.Contains(item.ID))
|
||||
{
|
||||
itemFrame.OutlineColor = itemFrame.Color = subInfo.BlockedDockingPortIDs.Contains(item.ID) ? GUI.Style.Red : GUI.Style.Green;
|
||||
itemFrame.OutlineColor = itemFrame.Color = subInfo.BlockedDockingPortIDs.Contains(item.ID) ? GUIStyle.Red : GUIStyle.Green;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -551,7 +560,7 @@ namespace Barotrauma
|
||||
}, disableElement: true);
|
||||
}
|
||||
|
||||
private void CreateRepairEntry(GUIComponent parent, string title, string imageStyle, int price, GUIButton.OnClickedHandler onPressed, bool isDisabled, Func<bool, bool>? onHover = null, bool disableElement = false)
|
||||
private void CreateRepairEntry(GUIComponent parent, LocalizedString title, string imageStyle, int price, GUIButton.OnClickedHandler onPressed, bool isDisabled, Func<bool, bool>? onHover = null, bool disableElement = false)
|
||||
{
|
||||
GUIFrame frameChild = new GUIFrame(rectT(new Point(parent.Rect.Width, (int) (96 * GUI.Scale)), parent), style: "UpgradeUIFrame");
|
||||
frameChild.SelectedColor = frameChild.Color;
|
||||
@@ -569,16 +578,16 @@ namespace Barotrauma
|
||||
GUILayoutGroup contentLayout = new GUILayoutGroup(rectT(0.9f, 0.85f, frameChild, Anchor.Center), isHorizontal: true);
|
||||
var repairIcon = new GUIFrame(rectT(new Point(contentLayout.Rect.Height, contentLayout.Rect.Height), contentLayout), style: imageStyle);
|
||||
GUILayoutGroup textLayout = new GUILayoutGroup(rectT(0.8f - repairIcon.RectTransform.RelativeSize.X, 1, contentLayout)) { Stretch = true };
|
||||
new GUITextBlock(rectT(1, 0, textLayout), title, font: GUI.SubHeadingFont) { CanBeFocused = false, AutoScaleHorizontal = true };
|
||||
new GUITextBlock(rectT(1, 0, textLayout), FormatCurrency(price));
|
||||
new GUITextBlock(rectT(1, 0, textLayout), title, font: GUIStyle.SubHeadingFont) { CanBeFocused = false, AutoScaleHorizontal = true };
|
||||
new GUITextBlock(rectT(1, 0, textLayout), TextManager.FormatCurrency(price));
|
||||
GUILayoutGroup buyButtonLayout = new GUILayoutGroup(rectT(0.2f, 1, contentLayout), childAnchor: Anchor.Center) { UserData = "buybutton" };
|
||||
new GUIButton(rectT(0.7f, 0.5f, buyButtonLayout), string.Empty, style: "RepairBuyButton") { ClickSound = GUISoundType.HireRepairClick, Enabled = AvailableMoney >= price && !isDisabled, OnClicked = onPressed };
|
||||
new GUIButton(rectT(0.7f, 0.5f, buyButtonLayout), string.Empty, style: "RepairBuyButton") { ClickSound = GUISoundType.HireRepairClick, Enabled = PlayerWallet.Balance >= price && !isDisabled, OnClicked = onPressed };
|
||||
contentLayout.Recalculate();
|
||||
buyButtonLayout.Recalculate();
|
||||
|
||||
if (disableElement)
|
||||
{
|
||||
frameChild.Enabled = AvailableMoney >= price && !isDisabled;
|
||||
frameChild.Enabled = PlayerWallet.Balance >= price && !isDisabled;
|
||||
}
|
||||
|
||||
if (!HasPermission)
|
||||
@@ -610,9 +619,9 @@ namespace Barotrauma
|
||||
|
||||
Dictionary<UpgradeCategory, List<UpgradePrefab>> upgrades = new Dictionary<UpgradeCategory, List<UpgradePrefab>>();
|
||||
|
||||
foreach (UpgradeCategory category in UpgradeCategory.Categories)
|
||||
foreach (UpgradeCategory category in UpgradeCategory.Categories.OrderBy(c => c.Name))
|
||||
{
|
||||
foreach (UpgradePrefab prefab in UpgradePrefab.Prefabs)
|
||||
foreach (UpgradePrefab prefab in UpgradePrefab.Prefabs.OrderBy(p => p.Name))
|
||||
{
|
||||
if (prefab.UpgradeCategories.Contains(category))
|
||||
{
|
||||
@@ -661,7 +670,7 @@ namespace Barotrauma
|
||||
* |-----------------------------|--------------------------|
|
||||
*/
|
||||
GUILayoutGroup contentLayout = new GUILayoutGroup(rectT(0.9f, 0.85f, frameChild, Anchor.Center));
|
||||
var itemCategoryLabel = new GUITextBlock(rectT(1, 1, contentLayout), category.Name, font: GUI.SubHeadingFont) { CanBeFocused = false };
|
||||
var itemCategoryLabel = new GUITextBlock(rectT(1, 1, contentLayout), category.Name, font: GUIStyle.SubHeadingFont) { CanBeFocused = false };
|
||||
GUILayoutGroup indicatorLayout = new GUILayoutGroup(rectT(0.5f, 0.25f, contentLayout, Anchor.BottomRight), isHorizontal: true, childAnchor: Anchor.TopRight) { UserData = "indicators", IgnoreLayoutGroups = true, RelativeSpacing = 0.01f };
|
||||
|
||||
foreach (var prefab in prefabs)
|
||||
@@ -742,7 +751,7 @@ namespace Barotrauma
|
||||
GUIComponent[] categoryFrames = GetFrames(category);
|
||||
foreach (GUIComponent itemFrame in itemPreviews.Values)
|
||||
{
|
||||
itemFrame.OutlineColor = itemFrame.Color = categoryFrames.Contains(itemFrame) ? GUI.Style.Orange : previewWhite;
|
||||
itemFrame.OutlineColor = itemFrame.Color = categoryFrames.Contains(itemFrame) ? GUIStyle.Orange : previewWhite;
|
||||
itemFrame.Children.ForEach(c => c.Color = itemFrame.Color);
|
||||
}
|
||||
|
||||
@@ -790,7 +799,7 @@ namespace Barotrauma
|
||||
GUIComponent[] categoryFrames = GetFrames(category);
|
||||
foreach (GUIComponent itemFrame in itemPreviews.Values)
|
||||
{
|
||||
itemFrame.OutlineColor = itemFrame.Color = categoryFrames.Contains(itemFrame) ? GUI.Style.Orange : previewWhite;
|
||||
itemFrame.OutlineColor = itemFrame.Color = categoryFrames.Contains(itemFrame) ? GUIStyle.Orange : previewWhite;
|
||||
itemFrame.Children.ForEach(c => c.Color = itemFrame.Color);
|
||||
}
|
||||
return true;
|
||||
@@ -851,8 +860,8 @@ namespace Barotrauma
|
||||
if (linkedItems.Min(it => it.ID) < item.ID) { return; }
|
||||
|
||||
var currentOrPending = item.PendingItemSwap ?? item.Prefab;
|
||||
string name = currentOrPending.Name;
|
||||
string nameWithQuantity = "";
|
||||
LocalizedString name = currentOrPending.Name;
|
||||
LocalizedString nameWithQuantity = "";
|
||||
if (linkedItems.Count > 1)
|
||||
{
|
||||
foreach (ItemPrefab distinctItem in linkedItems.Select(it => it.Prefab).Distinct())
|
||||
@@ -881,7 +890,7 @@ namespace Barotrauma
|
||||
};
|
||||
GUILayoutGroup buttonLayout = new GUILayoutGroup(rectT(1f, 1f, toggleButton.Frame), isHorizontal: true);
|
||||
|
||||
string slotText = "";
|
||||
LocalizedString slotText = "";
|
||||
if (linkedItems.Count > 1)
|
||||
{
|
||||
slotText = TextManager.GetWithVariable("weaponslot", "[number]", string.Join(", ", linkedItems.Select(it => (swappableEntities.IndexOf(it) + 1).ToString())));
|
||||
@@ -891,13 +900,13 @@ namespace Barotrauma
|
||||
slotText = TextManager.GetWithVariable("weaponslot", "[number]", (swappableEntities.IndexOf(item) + 1).ToString());
|
||||
}
|
||||
|
||||
new GUITextBlock(rectT(0.3f, 1f, buttonLayout), text: slotText, font: GUI.SubHeadingFont);
|
||||
new GUITextBlock(rectT(0.3f, 1f, buttonLayout), text: slotText, font: GUIStyle.SubHeadingFont);
|
||||
GUILayoutGroup group = new GUILayoutGroup(rectT(0.7f, 1f, buttonLayout), isHorizontal: true) { Stretch = true };
|
||||
|
||||
string title = item.PendingItemSwap != null ? TextManager.GetWithVariable("upgrades.pendingitem", "[itemname]", name) : nameWithQuantity;
|
||||
GUITextBlock text = new GUITextBlock(rectT(0.7f, 1f, group), text: title, font: GUI.SubHeadingFont, textAlignment: Alignment.Right, parseRichText: true)
|
||||
var title = item.PendingItemSwap != null ? TextManager.GetWithVariable("upgrades.pendingitem", "[itemname]", name) : nameWithQuantity;
|
||||
GUITextBlock text = new GUITextBlock(rectT(0.7f, 1f, group), text: RichString.Rich(title), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Right)
|
||||
{
|
||||
TextColor = GUI.Style.Orange
|
||||
TextColor = GUIStyle.Orange
|
||||
};
|
||||
GUIImage arrowImage = new GUIImage(rectT(0.5f, 1f, group, scaleBasis: ScaleBasis.BothHeight), style: "SlideDownArrow", scaleToFit: true);
|
||||
|
||||
@@ -911,7 +920,7 @@ namespace Barotrauma
|
||||
List<GUIFrame> frames = new List<GUIFrame>();
|
||||
if (currentOrPending != null)
|
||||
{
|
||||
bool canUninstall = item.PendingItemSwap != null || !string.IsNullOrEmpty(currentOrPending.SwappableItem?.ReplacementOnUninstall);
|
||||
bool canUninstall = item.PendingItemSwap != null || !(currentOrPending.SwappableItem?.ReplacementOnUninstall.IsEmpty ?? true);
|
||||
|
||||
bool isUninstallPending = item.Prefab.SwappableItem != null && item.PendingItemSwap?.Identifier == item.Prefab.SwappableItem.ReplacementOnUninstall;
|
||||
if (isUninstallPending) { canUninstall = false; }
|
||||
@@ -928,9 +937,7 @@ namespace Barotrauma
|
||||
{
|
||||
string textTag = item.PendingItemSwap != null ? "upgrades.cancelitemswappromptbody" : "upgrades.itemuninstallpromptbody";
|
||||
if (isUninstallPending) { textTag = "upgrades.cancelitemuninstallpromptbody"; }
|
||||
string promptBody = TextManager.GetWithVariables(textTag,
|
||||
new[] { "[itemtouninstall]" },
|
||||
new[] { isUninstallPending ? item.Name : currentOrPending.Name });
|
||||
LocalizedString promptBody = TextManager.GetWithVariable(textTag, "[itemtouninstall]", isUninstallPending ? item.Name : currentOrPending.Name);
|
||||
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("upgrades.refundprompttitle"), promptBody, () =>
|
||||
{
|
||||
if (GameMain.NetworkMember != null)
|
||||
@@ -965,14 +972,14 @@ namespace Barotrauma
|
||||
buttonStyle: isPurchased ? "WeaponInstallButton" : "StoreAddToCrateButton"));
|
||||
|
||||
if (!(frames.Last().FindChild(c => c is GUIButton, recursive: true) is GUIButton buyButton)) { continue; }
|
||||
if (Campaign.Money >= price)
|
||||
if (PlayerWallet.CanAfford(price))
|
||||
{
|
||||
buyButton.Enabled = true;
|
||||
buyButton.OnClicked += (button, o) =>
|
||||
{
|
||||
string promptBody = TextManager.GetWithVariables(isPurchased ? "upgrades.itemswappromptbody" : "upgrades.purchaseitemswappromptbody",
|
||||
new[] { "[itemtoinstall]", "[amount]" },
|
||||
new[] { replacement.Name, (replacement.SwappableItem.GetPrice(Campaign?.Map?.CurrentLocation) * linkedItems.Count).ToString() });
|
||||
LocalizedString promptBody = TextManager.GetWithVariables(isPurchased ? "upgrades.itemswappromptbody" : "upgrades.purchaseitemswappromptbody",
|
||||
("[itemtoinstall]", replacement.Name),
|
||||
("[amount]", (replacement.SwappableItem.GetPrice(Campaign?.Map?.CurrentLocation) * linkedItems.Count).ToString()));
|
||||
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), promptBody, () =>
|
||||
{
|
||||
if (GameMain.NetworkMember != null)
|
||||
@@ -1019,7 +1026,7 @@ namespace Barotrauma
|
||||
var linkedItems = Campaign.UpgradeManager.GetLinkedItemsToSwap(item);
|
||||
foreach (var itemPreview in itemPreviews)
|
||||
{
|
||||
itemPreview.Value.OutlineColor = itemPreview.Value.Color = linkedItems.Contains(itemPreview.Key) ? GUI.Style.Orange : previewWhite;
|
||||
itemPreview.Value.OutlineColor = itemPreview.Value.Color = linkedItems.Contains(itemPreview.Key) ? GUIStyle.Orange : previewWhite;
|
||||
}
|
||||
foreach (GUIComponent otherComponent in toggleButton.Parent.Children)
|
||||
{
|
||||
@@ -1041,7 +1048,7 @@ namespace Barotrauma
|
||||
foreach (var itemPreview in itemPreviews)
|
||||
{
|
||||
if (currentStoreLayout?.SelectedData is CategoryData categoryData && !categoryData.Category.ItemTags.Any(t => itemPreview.Key.HasTag(t))) { continue; }
|
||||
itemPreview.Value.OutlineColor = itemPreview.Value.Color = GUI.Style.Orange;
|
||||
itemPreview.Value.OutlineColor = itemPreview.Value.Color = GUIStyle.Orange;
|
||||
}
|
||||
}
|
||||
activeItemSwapSlideDown = toggleButton.Selected ? toggleButton : null;
|
||||
@@ -1058,7 +1065,7 @@ namespace Barotrauma
|
||||
return CreateUpgradeEntry(rectTransform, prefab.Sprite, prefab.Name, prefab.Description, price, new CategoryData(category, prefab), addBuyButton, upgradePrefab: prefab, currentLevel: campaign.UpgradeManager.GetUpgradeLevel(prefab, category));
|
||||
}
|
||||
|
||||
public static GUIFrame CreateUpgradeEntry(RectTransform parent, Sprite sprite, string title, string body, int price, object? userData, bool addBuyButton = true, bool addProgressBar = true, string buttonStyle = "UpgradeBuyButton", UpgradePrefab upgradePrefab = null, int currentLevel = 0)
|
||||
public static GUIFrame CreateUpgradeEntry(RectTransform parent, Sprite sprite, LocalizedString title, LocalizedString body, int price, object? userData, bool addBuyButton = true, bool addProgressBar = true, string buttonStyle = "UpgradeBuyButton", UpgradePrefab? upgradePrefab = null, int currentLevel = 0)
|
||||
{
|
||||
float progressBarHeight = 0.25f;
|
||||
|
||||
@@ -1080,29 +1087,29 @@ namespace Barotrauma
|
||||
GUILayoutGroup imageLayout = new GUILayoutGroup(rectT(new Point(prefabLayout.Rect.Height, prefabLayout.Rect.Height), prefabLayout), childAnchor: Anchor.Center);
|
||||
var icon = new GUIImage(rectT(0.9f, 0.9f, imageLayout, scaleBasis: ScaleBasis.BothHeight), sprite, scaleToFit: true) { CanBeFocused = false };
|
||||
GUILayoutGroup textLayout = new GUILayoutGroup(rectT(0.8f - imageLayout.RectTransform.RelativeSize.X, 1, prefabLayout));
|
||||
var name = new GUITextBlock(rectT(1, 0.25f, textLayout), title, font: GUI.SubHeadingFont, parseRichText: true) { AutoScaleHorizontal = true, AutoScaleVertical = true, Padding = Vector4.Zero };
|
||||
var name = new GUITextBlock(rectT(1, 0.25f, textLayout), RichString.Rich(title), font: GUIStyle.SubHeadingFont) { AutoScaleHorizontal = true, AutoScaleVertical = true, Padding = Vector4.Zero };
|
||||
GUILayoutGroup descriptionLayout = new GUILayoutGroup(rectT(1, 0.75f - progressBarHeight, textLayout));
|
||||
var description = new GUITextBlock(rectT(1, 1, descriptionLayout), body, font: GUI.SmallFont, wrap: true, textAlignment: Alignment.TopLeft) { Padding = Vector4.Zero };
|
||||
var description = new GUITextBlock(rectT(1, 1, descriptionLayout), body, font: GUIStyle.SmallFont, wrap: true, textAlignment: Alignment.TopLeft) { Padding = Vector4.Zero };
|
||||
GUILayoutGroup? progressLayout = null;
|
||||
GUILayoutGroup? buyButtonLayout = null;
|
||||
|
||||
if (addProgressBar)
|
||||
{
|
||||
progressLayout = new GUILayoutGroup(rectT(1, 0.25f, textLayout), isHorizontal: true, childAnchor: Anchor.CenterLeft) { UserData = "progressbar" };
|
||||
new GUIProgressBar(rectT(0.8f, 0.75f, progressLayout), 0.0f, GUI.Style.Orange);
|
||||
new GUITextBlock(rectT(0.2f, 1, progressLayout), string.Empty, font: GUI.SmallFont, textAlignment: Alignment.Center) { Padding = Vector4.Zero };
|
||||
new GUIProgressBar(rectT(0.8f, 0.75f, progressLayout), 0.0f, GUIStyle.Orange);
|
||||
new GUITextBlock(rectT(0.2f, 1, progressLayout), string.Empty, font: GUIStyle.SmallFont, textAlignment: Alignment.Center) { Padding = Vector4.Zero };
|
||||
}
|
||||
|
||||
if (addBuyButton)
|
||||
{
|
||||
string formattedPrice = FormatCurrency(Math.Abs(price));
|
||||
var formattedPrice = TextManager.FormatCurrency(Math.Abs(price));
|
||||
//negative price = refund
|
||||
if (price < 0) { formattedPrice = "+" + formattedPrice; }
|
||||
buyButtonLayout = new GUILayoutGroup(rectT(0.2f, 1, prefabLayout), childAnchor: Anchor.TopCenter) { UserData = "buybutton" };
|
||||
var priceText = new GUITextBlock(rectT(1, 0.2f, buyButtonLayout), formattedPrice, textAlignment: Alignment.Center);
|
||||
if (price < 0)
|
||||
{
|
||||
priceText.TextColor = GUI.Style.Green;
|
||||
priceText.TextColor = GUIStyle.Green;
|
||||
}
|
||||
else if (price == 0)
|
||||
{
|
||||
@@ -1120,8 +1127,8 @@ namespace Barotrauma
|
||||
// cut the description if it overflows and add a tooltip to it
|
||||
for (int i = 100; i > 0 && description.Rect.Height > descriptionLayout.Rect.Height; i--)
|
||||
{
|
||||
string[] lines = description.WrappedText.Split('\n');
|
||||
var newString = string.Join('\n', lines.Take(lines.Length - 1));
|
||||
var lines = description.WrappedText.Split('\n');
|
||||
var newString = string.Join('\n', lines.Take(lines.Count - 1));
|
||||
if (0 >= newString.Length - 4) { break; }
|
||||
|
||||
description.Text = newString.Substring(0, newString.Length - 4) + "...";
|
||||
@@ -1185,7 +1192,9 @@ namespace Barotrauma
|
||||
|
||||
buyButton.OnClicked += (button, o) =>
|
||||
{
|
||||
string promptBody = TextManager.GetWithVariables("Upgrades.PurchasePromptBody", new []{ "[upgradename]", "[amount]"}, new []{ prefab.Name, prefab.Price.GetBuyprice(Campaign.UpgradeManager.GetUpgradeLevel(prefab, category), Campaign.Map?.CurrentLocation).ToString() });
|
||||
LocalizedString promptBody = TextManager.GetWithVariables("Upgrades.PurchasePromptBody",
|
||||
("[upgradename]", prefab.Name),
|
||||
("[amount]", prefab.Price.GetBuyprice(Campaign.UpgradeManager.GetUpgradeLevel(prefab, category), Campaign.Map?.CurrentLocation).ToString()));
|
||||
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), promptBody, () =>
|
||||
{
|
||||
if (GameMain.NetworkMember != null)
|
||||
@@ -1225,7 +1234,7 @@ namespace Barotrauma
|
||||
itemName.Text = entity is Item ? entity.Name : TextManager.Get("upgradecategory.walls");
|
||||
if (slotIndex > -1)
|
||||
{
|
||||
itemName.Text = TextManager.GetWithVariables("weaponslotwithname", new string[] { "[number]", "[weaponname]" }, new string[] { slotIndex.ToString(), itemName.Text });
|
||||
itemName.Text = TextManager.GetWithVariables("weaponslotwithname", ("[number]", slotIndex.ToString()), ("[weaponname]", itemName.Text));
|
||||
}
|
||||
upgradeList.Content.ClearChildren();
|
||||
for (var i = 0; i < upgrades.Count && i < maxUpgrades; i++)
|
||||
@@ -1246,7 +1255,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (textBlock.UserData is Tuple<int, UpgradePrefab> tuple && tuple.Item2 == prefab)
|
||||
{
|
||||
string tooltip = CreateListEntry(tuple.Item2.Name, level + tuple.Item1);
|
||||
var tooltip = CreateListEntry(tuple.Item2.Name, level + tuple.Item1);
|
||||
textBlock.Text = tooltip;
|
||||
found = true;
|
||||
break;
|
||||
@@ -1275,7 +1284,7 @@ namespace Barotrauma
|
||||
moreIndicator.CalculateHeightFromText();
|
||||
layout.Recalculate();
|
||||
|
||||
static string CreateListEntry(string name, int level) => TextManager.GetWithVariables("upgradeuitooltip.upgradelistelement", new[] { "[upgradename]", "[level]" }, new[] { name, $"{level}" });
|
||||
static LocalizedString CreateListEntry(LocalizedString name, int level) => TextManager.GetWithVariables("upgradeuitooltip.upgradelistelement", ("[upgradename]", name), ("[level]", $"{level}"));
|
||||
}
|
||||
|
||||
public static IEnumerable<UpgradeCategory> GetApplicableCategories(Submarine drawnSubmarine)
|
||||
@@ -1294,7 +1303,9 @@ namespace Barotrauma
|
||||
{
|
||||
if (Campaign == null) { return; }
|
||||
|
||||
if (!parent.Children.Any() || Submarine.MainSub != null && Submarine.MainSub != drawnSubmarine || GameMain.GraphicsWidth != screenResolution.X || GameMain.GraphicsHeight != screenResolution.Y)
|
||||
if (!parent.Children.Any() ||
|
||||
Submarine.MainSub != null && Submarine.MainSub != drawnSubmarine ||
|
||||
GameMain.GraphicsWidth != screenResolution.X || GameMain.GraphicsHeight != screenResolution.Y)
|
||||
{
|
||||
GameMain.GameSession?.SubmarineInfo?.CheckSubsLeftBehind();
|
||||
drawnSubmarine = Submarine.MainSub;
|
||||
@@ -1312,6 +1323,10 @@ namespace Barotrauma
|
||||
// we also need this when we first load in so we know which category entries to disable since the CampaignUI is created before the submarine is loaded in.
|
||||
RefreshAll();
|
||||
}
|
||||
if (needsRefresh)
|
||||
{
|
||||
RefreshAll();
|
||||
}
|
||||
|
||||
// accept an active confirmation popup if any
|
||||
if (PlayerInput.KeyHit(Keys.Enter) && GUIMessageBox.MessageBoxes.Any())
|
||||
@@ -1334,16 +1349,16 @@ namespace Barotrauma
|
||||
{
|
||||
if (GUI.MouseOn == frame)
|
||||
{
|
||||
if (HoveredItem != item) { CreateItemTooltip(item); }
|
||||
HoveredItem = item;
|
||||
if (HoveredEntity != item) { CreateItemTooltip(item); }
|
||||
HoveredEntity = item;
|
||||
if (PlayerInput.PrimaryMouseButtonClicked() && selectedUpgradeTab == UpgradeTab.Upgrade && currentStoreLayout != null)
|
||||
{
|
||||
if (customizeTabOpen)
|
||||
{
|
||||
if (selectedUpgradeCategoryLayout != null)
|
||||
{
|
||||
var linkedItems = HoveredItem is Item ? Campaign.UpgradeManager.GetLinkedItemsToSwap((Item)HoveredItem) : new List<Item>();
|
||||
if (selectedUpgradeCategoryLayout.FindChild(c => c.UserData as Item == HoveredItem || linkedItems.Contains(c.UserData as Item), recursive: true) is GUIButton itemElement)
|
||||
var linkedItems = HoveredEntity is Item hoveredItem ? Campaign.UpgradeManager.GetLinkedItemsToSwap(hoveredItem) : new List<Item>();
|
||||
if (selectedUpgradeCategoryLayout.FindChild(c => c.UserData is Item item && (item == HoveredEntity || linkedItems.Contains(item)), recursive: true) is GUIButton itemElement)
|
||||
{
|
||||
if (!itemElement.Selected) { itemElement.OnClicked(itemElement, itemElement.UserData); }
|
||||
(itemElement.Parent?.Parent?.Parent as GUIListBox)?.ScrollToElement(itemElement);
|
||||
@@ -1370,8 +1385,8 @@ namespace Barotrauma
|
||||
// use pnpoly algorithm to detect if our mouse is within any of the hull polygons
|
||||
if (subHullVertices.Any(hullVertex => ToolBox.PointIntersectsWithPolygon(PlayerInput.MousePosition, hullVertex)))
|
||||
{
|
||||
if (HoveredItem != firstStructure && !(firstStructure is null)) { CreateItemTooltip(firstStructure); }
|
||||
HoveredItem = firstStructure;
|
||||
if (HoveredEntity != firstStructure && !(firstStructure is null)) { CreateItemTooltip(firstStructure); }
|
||||
HoveredEntity = firstStructure;
|
||||
isMouseOnStructure = true;
|
||||
GUI.MouseCursor = CursorState.Hand;
|
||||
|
||||
@@ -1382,7 +1397,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (!isMouseOnStructure) { HoveredItem = null; }
|
||||
if (!isMouseOnStructure) { HoveredEntity = null; }
|
||||
}
|
||||
|
||||
// flip the tooltip if it is outside of the screen
|
||||
@@ -1417,9 +1432,9 @@ namespace Barotrauma
|
||||
*/
|
||||
submarineInfoFrame = new GUILayoutGroup(rectT(0.25f, 0.2f, mainStoreLayout, Anchor.TopRight)) { IgnoreLayoutGroups = true };
|
||||
// submarine name
|
||||
new GUITextBlock(rectT(1, 0, submarineInfoFrame), submarine.Info.DisplayName, textAlignment: Alignment.Right, font: GUI.LargeFont);
|
||||
new GUITextBlock(rectT(1, 0, submarineInfoFrame), submarine.Info.DisplayName, textAlignment: Alignment.Right, font: GUIStyle.LargeFont);
|
||||
// submarine class
|
||||
new GUITextBlock(rectT(1, 0, submarineInfoFrame), $"{TextManager.GetWithVariable("submarineclass.classsuffixformat", "[type]", TextManager.Get($"submarineclass.{submarine.Info.SubmarineClass}"))}", textAlignment: Alignment.Right, font: GUI.Font);
|
||||
new GUITextBlock(rectT(1, 0, submarineInfoFrame), $"{TextManager.GetWithVariable("submarineclass.classsuffixformat", "[type]", TextManager.Get($"submarineclass.{submarine.Info.SubmarineClass}"))}", textAlignment: Alignment.Right, font: GUIStyle.Font);
|
||||
var description = new GUITextBlock(rectT(1, 0, submarineInfoFrame), submarine.Info.Description, textAlignment: Alignment.Right, wrap: true);
|
||||
submarineInfoFrame.RectTransform.ScreenSpaceOffset = new Point(0, (int)(16 * GUI.Scale));
|
||||
|
||||
@@ -1448,7 +1463,7 @@ namespace Barotrauma
|
||||
Point size = new Point((int) (spriteSize * item.Scale / dockedBorders.Width * hullContainer.Rect.Width));
|
||||
itemFrame = new GUIImage(rectT(size, component, Anchor.Center), icon, scaleToFit: true)
|
||||
{
|
||||
SelectedColor = GUI.Style.Orange,
|
||||
SelectedColor = GUIStyle.Orange,
|
||||
Color = previewWhite,
|
||||
HoverCursor = CursorState.Hand,
|
||||
SpriteEffects = item.Rotation > 90.0f && item.Rotation < 270.0f ? SpriteEffects.FlipVertically : SpriteEffects.None
|
||||
@@ -1457,7 +1472,7 @@ namespace Barotrauma
|
||||
{
|
||||
new GUIImage(new RectTransform(new Vector2(0.8f), itemFrame.RectTransform, Anchor.TopLeft) { RelativeOffset = new Vector2(-0.2f) }, "WeaponSwitchIcon.DropShadow", scaleToFit: true)
|
||||
{
|
||||
SelectedColor = GUI.Style.Orange,
|
||||
SelectedColor = GUIStyle.Orange,
|
||||
Color = previewWhite,
|
||||
CanBeFocused = false
|
||||
};
|
||||
@@ -1468,7 +1483,7 @@ namespace Barotrauma
|
||||
Point size = new Point((int) (item.Rect.Width * item.Scale / dockedBorders.Width * hullContainer.Rect.Width), (int) (item.Rect.Height * item.Scale / dockedBorders.Height * hullContainer.Rect.Height));
|
||||
itemFrame = new GUIFrame(rectT(size, component, Anchor.Center), style: "ScanLines")
|
||||
{
|
||||
SelectedColor = GUI.Style.Orange,
|
||||
SelectedColor = GUIStyle.Orange,
|
||||
OutlineColor = previewWhite,
|
||||
Color = previewWhite,
|
||||
OutlineThickness = 2,
|
||||
@@ -1540,7 +1555,7 @@ namespace Barotrauma
|
||||
// calculate the center point so we can draw a line from X to Y instead of drawing a rotated rectangle that is filled
|
||||
Vector2 point1 = hullVertex[1] + (hullVertex[2] - hullVertex[1]) / 2;
|
||||
Vector2 point2 = hullVertex[0] + (hullVertex[3] - hullVertex[0]) / 2;
|
||||
GUI.DrawLine(spriteBatch, point1, point2, (highlightWalls ? GUI.Style.Orange * 0.6f : Color.DarkCyan * 0.3f), width: 10);
|
||||
GUI.DrawLine(spriteBatch, point1, point2, (highlightWalls ? GUIStyle.Orange * 0.6f : Color.DarkCyan * 0.3f), width: 10);
|
||||
if (GameMain.DebugDraw)
|
||||
{
|
||||
// the "collision box" is a bit bigger than the line we draw so this can be useful data (maybe)
|
||||
@@ -1553,14 +1568,14 @@ namespace Barotrauma
|
||||
{
|
||||
int currentLevel = campaign.UpgradeManager.GetUpgradeLevel(prefab, category);
|
||||
|
||||
string progressText = TextManager.GetWithVariables("upgrades.progressformat", new[] { "[level]", "[maxlevel]" }, new[] { currentLevel.ToString(), prefab.MaxLevel.ToString() });
|
||||
LocalizedString progressText = TextManager.GetWithVariables("upgrades.progressformat", ("[level]", currentLevel.ToString()), ("[maxlevel]", prefab.MaxLevel.ToString()));
|
||||
if (prefabFrame.FindChild("progressbar", true) is { } progressParent)
|
||||
{
|
||||
GUIProgressBar bar = progressParent.GetChild<GUIProgressBar>();
|
||||
if (bar != null)
|
||||
{
|
||||
bar.BarSize = currentLevel / (float) prefab.MaxLevel;
|
||||
bar.Color = currentLevel >= prefab.MaxLevel ? GUI.Style.Green : GUI.Style.Orange;
|
||||
bar.Color = currentLevel >= prefab.MaxLevel ? GUIStyle.Green : GUIStyle.Orange;
|
||||
}
|
||||
|
||||
GUITextBlock block = progressParent.GetChild<GUITextBlock>();
|
||||
@@ -1576,18 +1591,18 @@ namespace Barotrauma
|
||||
|
||||
if (priceLabel != null && !WaitForServerUpdate)
|
||||
{
|
||||
priceLabel.Text = FormatCurrency(price);
|
||||
priceLabel.Text = TextManager.FormatCurrency(price);
|
||||
if (currentLevel >= prefab.MaxLevel)
|
||||
{
|
||||
priceLabel.Text = TextManager.Get("Upgrade.MaxedUpgrade");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GUIButton button = buttonParent.GetChild<GUIButton>();
|
||||
if (button != null)
|
||||
{
|
||||
button.Enabled = currentLevel < prefab.MaxLevel;
|
||||
if (WaitForServerUpdate || !campaign.AllowedToManageCampaign() || price > campaign.Money)
|
||||
if (WaitForServerUpdate || !campaign.Wallet.CanAfford(price))
|
||||
{
|
||||
button.Enabled = false;
|
||||
}
|
||||
@@ -1620,7 +1635,7 @@ namespace Barotrauma
|
||||
else
|
||||
{
|
||||
parent.Enabled = false;
|
||||
parent.SelectedColor = GUI.Style.Red * 0.5f;
|
||||
parent.SelectedColor = GUIStyle.Red * 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1632,12 +1647,12 @@ namespace Barotrauma
|
||||
{
|
||||
if (component.UserData != prefab) { continue; }
|
||||
|
||||
Dictionary<string, GUIComponentStyle> styles = GUI.Style.GetComponentStyle("upgradeindicator").ChildStyles;
|
||||
Dictionary<Identifier, GUIComponentStyle> styles = GUIStyle.GetComponentStyle("upgradeindicator").ChildStyles;
|
||||
if (!styles.ContainsKey("upgradeindicatoron") || !styles.ContainsKey("upgradeindicatordim") || !styles.ContainsKey("upgradeindicatoroff")) { continue; }
|
||||
|
||||
GUIComponentStyle onStyle = styles["upgradeindicatoron"];
|
||||
GUIComponentStyle dimStyle = styles["upgradeindicatordim"];
|
||||
GUIComponentStyle offStyle = styles["upgradeindicatoroff"];
|
||||
GUIComponentStyle onStyle = styles["upgradeindicatoron".ToIdentifier()];
|
||||
GUIComponentStyle dimStyle = styles["upgradeindicatordim".ToIdentifier()];
|
||||
GUIComponentStyle offStyle = styles["upgradeindicatoroff".ToIdentifier()];
|
||||
|
||||
if (campaign.UpgradeManager.GetUpgradeLevel(prefab, category) >= prefab.MaxLevel)
|
||||
{
|
||||
@@ -1692,12 +1707,7 @@ namespace Barotrauma
|
||||
return frames.ToArray();
|
||||
}
|
||||
|
||||
private bool HasPermission => campaignUI.Campaign.AllowedToManageCampaign();
|
||||
|
||||
public static string FormatCurrency(int money, bool format = true)
|
||||
{
|
||||
return TextManager.GetWithVariable("CurrencyFormat", "[credits]", format ? string.Format(CultureInfo.InvariantCulture, "{0:N0}", money) : money.ToString());
|
||||
}
|
||||
private bool HasPermission => true;
|
||||
|
||||
// just a shortcut to create new RectTransforms since all the new RectTransform and new Vector2 confuses my IDE (and me)
|
||||
private static RectTransform rectT(float x, float y, GUIComponent parentComponent, Anchor anchor = Anchor.TopLeft, ScaleBasis scaleBasis = ScaleBasis.Normal)
|
||||
|
||||
@@ -34,23 +34,29 @@ namespace Barotrauma
|
||||
|
||||
public class TextSettings
|
||||
{
|
||||
public string Text;
|
||||
public LocalizedString Text;
|
||||
public int Width;
|
||||
|
||||
public TextSettings(Identifier textTag, int width)
|
||||
{
|
||||
Text = TextManager.GetFormatted(textTag);
|
||||
Width = width;
|
||||
}
|
||||
|
||||
public TextSettings(XElement element)
|
||||
{
|
||||
Text = TextManager.GetFormatted(element.GetAttributeString("text", string.Empty), true);
|
||||
Text = TextManager.GetFormatted(element.GetAttributeIdentifier("text", Identifier.Empty));
|
||||
Width = element.GetAttributeInt("width", 450);
|
||||
}
|
||||
}
|
||||
|
||||
public class VideoSettings
|
||||
{
|
||||
public string File;
|
||||
public readonly string File;
|
||||
|
||||
public VideoSettings(XElement element)
|
||||
public VideoSettings(string file)
|
||||
{
|
||||
File = element.GetAttributeString("file", string.Empty);
|
||||
File = file;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,13 +81,13 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
videoView = new GUICustomComponent(new RectTransform(Point.Zero, videoFrame.RectTransform, Anchor.Center), (spriteBatch, guiCustomComponent) => { DrawVideo(spriteBatch, guiCustomComponent.Rect); });
|
||||
title = new GUITextBlock(new RectTransform(Point.Zero, textFrame.RectTransform, Anchor.TopLeft, Pivot.TopLeft), string.Empty, font: GUI.LargeFont, textColor: new Color(253, 174, 0), textAlignment: Alignment.Left);
|
||||
title = new GUITextBlock(new RectTransform(Point.Zero, textFrame.RectTransform, Anchor.TopLeft, Pivot.TopLeft), string.Empty, font: GUIStyle.LargeFont, textColor: new Color(253, 174, 0), textAlignment: Alignment.Left);
|
||||
|
||||
textContent = new GUITextBlock(new RectTransform(Point.Zero, textFrame.RectTransform, Anchor.TopLeft, Pivot.TopLeft), string.Empty, font: GUI.Font, textAlignment: Alignment.TopLeft);
|
||||
textContent = new GUITextBlock(new RectTransform(Point.Zero, textFrame.RectTransform, Anchor.TopLeft, Pivot.TopLeft), string.Empty, font: GUIStyle.Font, textAlignment: Alignment.TopLeft);
|
||||
|
||||
objectiveTitle = new GUITextBlock(new RectTransform(new Vector2(1f, 0f), textFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter), string.Empty, font: GUI.SubHeadingFont, textAlignment: Alignment.CenterRight, textColor: Color.White);
|
||||
objectiveTitle = new GUITextBlock(new RectTransform(new Vector2(1f, 0f), textFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter), string.Empty, font: GUIStyle.SubHeadingFont, textAlignment: Alignment.CenterRight, textColor: Color.White);
|
||||
objectiveTitle.Text = TextManager.Get("Tutorial.NewObjective");
|
||||
objectiveText = new GUITextBlock(new RectTransform(Point.Zero, textFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter), string.Empty, font: GUI.SubHeadingFont, textColor: new Color(4, 180, 108), textAlignment: Alignment.CenterRight);
|
||||
objectiveText = new GUITextBlock(new RectTransform(Point.Zero, textFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter), string.Empty, font: GUIStyle.SubHeadingFont, textColor: new Color(4, 180, 108), textAlignment: Alignment.CenterRight);
|
||||
|
||||
objectiveTitle.Visible = objectiveText.Visible = false;
|
||||
}
|
||||
@@ -120,7 +126,12 @@ namespace Barotrauma
|
||||
background.AddToGUIUpdateList(ignoreChildren, order);
|
||||
}
|
||||
|
||||
public void LoadContent(string contentPath, VideoSettings videoSettings, TextSettings textSettings, string contentId, bool startPlayback, string objective = "", Action callback = null)
|
||||
public void LoadContent(string contentPath, VideoSettings videoSettings, TextSettings textSettings, Identifier contentId, bool startPlayback)
|
||||
{
|
||||
LoadContent(contentPath, videoSettings, textSettings, contentId, startPlayback, new RawLString(""), null);
|
||||
}
|
||||
|
||||
public void LoadContent(string contentPath, VideoSettings videoSettings, TextSettings textSettings, Identifier contentId, bool startPlayback, LocalizedString objective, Action callback = null)
|
||||
{
|
||||
callbackOnStop = callback;
|
||||
filePath = contentPath + videoSettings.File;
|
||||
@@ -183,10 +194,10 @@ namespace Barotrauma
|
||||
title.RectTransform.NonScaledSize = new Point(scaledTextWidth, scaledTitleHeight);
|
||||
title.RectTransform.AbsoluteOffset = new Point((int)(5 * GUI.Scale), (int)(10 * GUI.Scale));
|
||||
|
||||
if (textSettings != null && !string.IsNullOrEmpty(textSettings.Text))
|
||||
if (textSettings != null && !textSettings.Text.IsNullOrEmpty())
|
||||
{
|
||||
textSettings.Text = ToolBox.WrapText(textSettings.Text, scaledTextWidth, GUI.Font);
|
||||
int wrappedHeight = textSettings.Text.Split('\n').Length * scaledTextHeight;
|
||||
textSettings.Text = ToolBox.WrapText(textSettings.Text, scaledTextWidth, GUIStyle.Font);
|
||||
int wrappedHeight = textSettings.Text.Value.Split('\n').Length * scaledTextHeight;
|
||||
|
||||
textFrame.RectTransform.NonScaledSize = new Point(scaledTextWidth + scaledBorderSize, wrappedHeight + scaledBorderSize + scaledButtonSize.Y + scaledTitleHeight);
|
||||
|
||||
@@ -203,7 +214,7 @@ namespace Barotrauma
|
||||
textContent.RectTransform.AbsoluteOffset = new Point(0, scaledBorderSize + scaledTitleHeight);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(objectiveText.Text))
|
||||
if (!objectiveText.Text.IsNullOrEmpty())
|
||||
{
|
||||
int scaledXOffset = (int)(-10 * GUI.Scale);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
@@ -19,32 +19,54 @@ namespace Barotrauma
|
||||
private Func<int> getYesVotes, getNoVotes, getMaxVotes;
|
||||
private bool votePassed;
|
||||
|
||||
private string votingOnText;
|
||||
private List<RichTextData> votingOnTextData;
|
||||
private RichString votingOnText;
|
||||
private float votingTime = 100f;
|
||||
private float timer;
|
||||
private VoteType currentVoteType;
|
||||
private Color submarineColor => GUI.Style.Orange;
|
||||
private Color SubmarineColor => GUIStyle.Orange;
|
||||
private Point createdForResolution;
|
||||
|
||||
public VotingInterface(Client starter, SubmarineInfo info, VoteType type, float votingTime)
|
||||
public static VotingInterface CreateSubmarineVotingInterface(Client starter, SubmarineInfo info, VoteType type, float votingTime)
|
||||
{
|
||||
if (starter == null || info == null) return;
|
||||
SetSubmarineVotingText(starter, info, type);
|
||||
this.votingTime = votingTime;
|
||||
getYesVotes = SubmarineYesVotes;
|
||||
getNoVotes = SubmarineNoVotes;
|
||||
getMaxVotes = SubmarineMaxVotes;
|
||||
onVoteEnd = () => SendSubmarineVoteEndMessage(info, type);
|
||||
if (starter == null || info == null) { return null; }
|
||||
|
||||
Initialize(starter, type);
|
||||
var subVoting = new VotingInterface()
|
||||
{
|
||||
votingTime = votingTime,
|
||||
getYesVotes = () => GameMain.NetworkMember?.Voting?.GetVoteCountYes(type) ?? 0,
|
||||
getNoVotes = () => GameMain.NetworkMember?.Voting?.GetVoteCountNo(type) ?? 0,
|
||||
getMaxVotes = () => GameMain.NetworkMember?.Voting?.GetVoteCountMax(type) ?? 0,
|
||||
};
|
||||
subVoting.onVoteEnd = () => subVoting.SendSubmarineVoteEndMessage(info, type);
|
||||
subVoting.SetSubmarineVotingText(starter, info, type);
|
||||
subVoting.Initialize(starter, type);
|
||||
return subVoting;
|
||||
}
|
||||
|
||||
public static VotingInterface CreateMoneyTransferVotingInterface(Client starter, Client from, Client to, int amount, float votingTime)
|
||||
{
|
||||
if (starter == null) { return null; }
|
||||
if (from == null && to == null) { return null; }
|
||||
|
||||
var transferVoting = new VotingInterface()
|
||||
{
|
||||
votingTime = votingTime,
|
||||
getYesVotes = () => GameMain.NetworkMember?.Voting?.GetVoteCountYes(VoteType.TransferMoney) ?? 0,
|
||||
getNoVotes = () => GameMain.NetworkMember?.Voting?.GetVoteCountNo(VoteType.TransferMoney) ?? 0,
|
||||
getMaxVotes = () => GameMain.NetworkMember?.Voting?.GetVoteCountMax(VoteType.TransferMoney) ?? 0,
|
||||
};
|
||||
transferVoting.onVoteEnd = () => transferVoting.SendMoneyTransferVoteEndMessage(from, to, amount);
|
||||
transferVoting.SetMoneyTransferVotingText(starter, from, to, amount);
|
||||
transferVoting.Initialize(starter, VoteType.TransferMoney);
|
||||
return transferVoting;
|
||||
}
|
||||
|
||||
|
||||
private void Initialize(Client starter, VoteType type)
|
||||
{
|
||||
currentVoteType = type;
|
||||
CreateVotingGUI();
|
||||
if (starter.ID == GameMain.Client.ID) SetGUIToVotedState(2);
|
||||
if (starter.ID == GameMain.Client.ID) { SetGUIToVotedState(2); }
|
||||
VoteRunning = true;
|
||||
}
|
||||
|
||||
@@ -52,7 +74,7 @@ namespace Barotrauma
|
||||
{
|
||||
createdForResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||
|
||||
if (frame != null) frame.Parent.RemoveChild(frame);
|
||||
frame?.Parent.RemoveChild(frame);
|
||||
frame = new GUIFrame(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.VotingArea, GameMain.Client.InGameHUD.RectTransform), style: "");
|
||||
|
||||
int padding = HUDLayoutSettings.Padding * 2;
|
||||
@@ -60,14 +82,14 @@ namespace Barotrauma
|
||||
int yOffset = padding;
|
||||
int paddedWidth = frame.Rect.Width - padding * 2;
|
||||
|
||||
votingTextBlock = new GUITextBlock(new RectTransform(new Point(paddedWidth, 0), frame.RectTransform), votingOnTextData, votingOnText, wrap: true);
|
||||
votingTextBlock = new GUITextBlock(new RectTransform(new Point(paddedWidth, 0), frame.RectTransform), votingOnText, wrap: true);
|
||||
votingTextBlock.RectTransform.NonScaledSize = votingTextBlock.RectTransform.MinSize = votingTextBlock.RectTransform.MaxSize = new Point(votingTextBlock.Rect.Width, votingTextBlock.Rect.Height);
|
||||
votingTextBlock.RectTransform.IsFixedSize = true;
|
||||
votingTextBlock.RectTransform.AbsoluteOffset = new Point(padding, yOffset);
|
||||
|
||||
yOffset += votingTextBlock.Rect.Height + spacing;
|
||||
|
||||
voteCounter = new GUITextBlock(new RectTransform(new Point(paddedWidth, 0), frame.RectTransform), "(0/0)", GUI.Style.Green, textAlignment: Alignment.Center);
|
||||
voteCounter = new GUITextBlock(new RectTransform(new Point(paddedWidth, 0), frame.RectTransform), "(0/0)", GUIStyle.Green, textAlignment: Alignment.Center);
|
||||
voteCounter.RectTransform.NonScaledSize = voteCounter.RectTransform.MinSize = voteCounter.RectTransform.MaxSize = new Point(voteCounter.Rect.Width, voteCounter.Rect.Height);
|
||||
voteCounter.RectTransform.IsFixedSize = true;
|
||||
voteCounter.RectTransform.AbsoluteOffset = new Point(padding, yOffset);
|
||||
@@ -118,8 +140,8 @@ namespace Barotrauma
|
||||
|
||||
public void Update(float deltaTime)
|
||||
{
|
||||
if (!VoteRunning) return;
|
||||
if (GameMain.GraphicsWidth != createdForResolution.X || GameMain.GraphicsHeight != createdForResolution.Y) CreateVotingGUI();
|
||||
if (!VoteRunning) { return; }
|
||||
if (GameMain.GraphicsWidth != createdForResolution.X || GameMain.GraphicsHeight != createdForResolution.Y) { CreateVotingGUI(); }
|
||||
yesVotes = getYesVotes();
|
||||
noVotes = getNoVotes();
|
||||
maxVotes = getMaxVotes();
|
||||
@@ -128,7 +150,6 @@ namespace Barotrauma
|
||||
votingTimer.BarSize = timer / votingTime;
|
||||
}
|
||||
|
||||
|
||||
public void EndVote(bool passed, int yesVoteFinal, int noVoteFinal)
|
||||
{
|
||||
VoteRunning = false;
|
||||
@@ -145,75 +166,94 @@ namespace Barotrauma
|
||||
JobPrefab prefab = starter?.Character?.Info?.Job?.Prefab;
|
||||
Color nameColor = prefab != null ? prefab.UIColor : Color.White;
|
||||
string characterRichString = $"‖color:{nameColor.R},{nameColor.G},{nameColor.B}‖{name}‖color:end‖";
|
||||
string submarineRichString = $"‖color:{submarineColor.R},{submarineColor.G},{submarineColor.B}‖{info.DisplayName}‖color:end‖";
|
||||
string submarineRichString = $"‖color:{SubmarineColor.R},{SubmarineColor.G},{SubmarineColor.B}‖{info.DisplayName}‖color:end‖";
|
||||
|
||||
LocalizedString text = string.Empty;
|
||||
switch (type)
|
||||
{
|
||||
case VoteType.PurchaseAndSwitchSub:
|
||||
votingOnText = TextManager.GetWithVariables("submarinepurchaseandswitchvote", new string[] { "[playername]", "[submarinename]", "[amount]", "[currencyname]" }, new string[] { characterRichString, submarineRichString, info.Price.ToString(), TextManager.Get("credit").ToLower() });
|
||||
text = TextManager.GetWithVariables("submarinepurchaseandswitchvote",
|
||||
("[playername]", characterRichString),
|
||||
("[submarinename]", submarineRichString),
|
||||
("[amount]", info.Price.ToString()),
|
||||
("[currencyname]", TextManager.Get("credit").ToLower()));
|
||||
break;
|
||||
case VoteType.PurchaseSub:
|
||||
votingOnText = TextManager.GetWithVariables("submarinepurchasevote", new string[] { "[playername]", "[submarinename]", "[amount]", "[currencyname]" }, new string[] { characterRichString, submarineRichString, info.Price.ToString(), TextManager.Get("credit").ToLower() });
|
||||
text = TextManager.GetWithVariables("submarinepurchasevote",
|
||||
("[playername]", characterRichString),
|
||||
("[submarinename]", submarineRichString),
|
||||
("[amount]", info.Price.ToString()),
|
||||
("[currencyname]", TextManager.Get("credit").ToLower()));
|
||||
break;
|
||||
case VoteType.SwitchSub:
|
||||
int deliveryFee = SubmarineSelection.DeliveryFeePerDistanceTravelled * GameMain.GameSession.Map.DistanceToClosestLocationWithOutpost(GameMain.GameSession.Map.CurrentLocation, out Location endLocation);
|
||||
|
||||
if (deliveryFee > 0)
|
||||
{
|
||||
votingOnText = TextManager.GetWithVariables("submarineswitchfeevote", new string[] { "[playername]", "[submarinename]", "[locationname]", "[amount]", "[currencyname]" }, new string[] { characterRichString, submarineRichString, endLocation.Name, deliveryFee.ToString(), TextManager.Get("credit").ToLower() });
|
||||
text = TextManager.GetWithVariables("submarineswitchfeevote",
|
||||
("[playername]", characterRichString),
|
||||
("[submarinename]", submarineRichString),
|
||||
("[locationname]", endLocation.Name),
|
||||
("[amount]", deliveryFee.ToString()),
|
||||
("[currencyname]", TextManager.Get("credit").ToLower()));
|
||||
}
|
||||
else
|
||||
{
|
||||
votingOnText = TextManager.GetWithVariables("submarineswitchnofeevote", new string[] { "[playername]", "[submarinename]" }, new string[] { characterRichString, submarineRichString });
|
||||
text = TextManager.GetWithVariables("submarineswitchnofeevote",
|
||||
("[playername]", characterRichString),
|
||||
("[submarinename]", submarineRichString));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
votingOnTextData = RichTextData.GetRichTextData(votingOnText, out votingOnText);
|
||||
}
|
||||
|
||||
private int SubmarineYesVotes()
|
||||
{
|
||||
return GameMain.NetworkMember.SubmarineVoteYesCount;
|
||||
}
|
||||
|
||||
private int SubmarineNoVotes()
|
||||
{
|
||||
return GameMain.NetworkMember.SubmarineVoteNoCount;
|
||||
}
|
||||
|
||||
private int SubmarineMaxVotes()
|
||||
{
|
||||
return GameMain.NetworkMember.SubmarineVoteMax;
|
||||
votingOnText = RichString.Rich(text);
|
||||
}
|
||||
|
||||
private void SendSubmarineVoteEndMessage(SubmarineInfo info, VoteType type)
|
||||
{
|
||||
GameMain.NetworkMember.AddChatMessage(GetSubmarineVoteResultMessage(info, type, yesVotes.ToString(), noVotes.ToString(), votePassed), ChatMessageType.Server);
|
||||
GameMain.NetworkMember.AddChatMessage(GetSubmarineVoteResultMessage(info, type, yesVotes, noVotes, votePassed).Value, ChatMessageType.Server);
|
||||
}
|
||||
|
||||
public static string GetSubmarineVoteResultMessage(SubmarineInfo info, VoteType type, string yesVoteString, string noVoteString, bool votePassed)
|
||||
private LocalizedString GetSubmarineVoteResultMessage(SubmarineInfo info, VoteType type, int yesVoteCount, int noVoteCount, bool votePassed)
|
||||
{
|
||||
string result = string.Empty;
|
||||
LocalizedString result = string.Empty;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case VoteType.PurchaseAndSwitchSub:
|
||||
result = TextManager.GetWithVariables(votePassed ? "submarinepurchaseandswitchvotepassed" : "submarinepurchaseandswitchvotefailed", new string[] { "[submarinename]", "[amount]", "[currencyname]", "[yesvotecount]", "[novotecount]" }, new string[] { info.DisplayName, info.Price.ToString(), TextManager.Get("credit").ToLower(), yesVoteString, noVoteString });
|
||||
result = TextManager.GetWithVariables(votePassed ? "submarinepurchaseandswitchvotepassed" : "submarinepurchaseandswitchvotefailed",
|
||||
("[submarinename]", info.DisplayName),
|
||||
("[amount]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", info.Price)),
|
||||
("[currencyname]", TextManager.Get("credit").ToLower()),
|
||||
("[yesvotecount]", yesVoteCount.ToString()),
|
||||
("[novotecount]" , noVoteCount.ToString()));
|
||||
break;
|
||||
case VoteType.PurchaseSub:
|
||||
result = TextManager.GetWithVariables(votePassed ? "submarinepurchasevotepassed" : "submarinepurchasevotefailed", new string[] { "[submarinename]", "[amount]", "[currencyname]", "[yesvotecount]", "[novotecount]" }, new string[] { info.DisplayName, info.Price.ToString(), TextManager.Get("credit").ToLower(), yesVoteString, noVoteString });
|
||||
result = TextManager.GetWithVariables(votePassed ? "submarinepurchasevotepassed" : "submarinepurchasevotefailed",
|
||||
("[submarinename]", info.DisplayName),
|
||||
("[amount]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", info.Price)),
|
||||
("[currencyname]", TextManager.Get("credit").ToLower()),
|
||||
("[yesvotecount]", yesVoteCount.ToString()),
|
||||
("[novotecount]", noVoteCount.ToString()));
|
||||
break;
|
||||
case VoteType.SwitchSub:
|
||||
int deliveryFee = SubmarineSelection.DeliveryFeePerDistanceTravelled * GameMain.GameSession.Map.DistanceToClosestLocationWithOutpost(GameMain.GameSession.Map.CurrentLocation, out Location endLocation);
|
||||
|
||||
if (deliveryFee > 0)
|
||||
{
|
||||
result = TextManager.GetWithVariables(votePassed ? "submarineswitchfeevotepassed" : "submarineswitchfeevotefailed", new string[] { "[submarinename]", "[locationname]", "[amount]", "[currencyname]", "[yesvotecount]", "[novotecount]" }, new string[] { info.DisplayName, endLocation.Name, deliveryFee.ToString(), TextManager.Get("credit").ToLower(), yesVoteString, noVoteString });
|
||||
result = TextManager.GetWithVariables(votePassed ? "submarineswitchfeevotepassed" : "submarineswitchfeevotefailed",
|
||||
("[submarinename]", info.DisplayName),
|
||||
("[locationname]", endLocation.Name),
|
||||
("[amount]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", deliveryFee)),
|
||||
("[currencyname]", TextManager.Get("credit").ToLower()),
|
||||
("[yesvotecount]", yesVoteCount.ToString()),
|
||||
("[novotecount]", noVoteCount.ToString()));
|
||||
}
|
||||
else
|
||||
{
|
||||
result = TextManager.GetWithVariables(votePassed ? "submarineswitchnofeevotepassed" : "submarineswitchnofeevotefailed", new string[] { "[submarinename]", "[yesvotecount]", "[novotecount]" }, new string[] { info.DisplayName, yesVoteString, noVoteString });
|
||||
result = TextManager.GetWithVariables(votePassed ? "submarineswitchnofeevotepassed" : "submarineswitchnofeevotefailed",
|
||||
("[submarinename]", info.DisplayName),
|
||||
("[yesvotecount]", yesVoteCount.ToString()),
|
||||
("[novotecount]", noVoteCount.ToString()));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -223,6 +263,58 @@ namespace Barotrauma
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
private void SetMoneyTransferVotingText(Client starter, Client from, Client to, int amount)
|
||||
{
|
||||
string name = starter.Name;
|
||||
JobPrefab prefab = starter?.Character?.Info?.Job?.Prefab;
|
||||
Color nameColor = prefab != null ? prefab.UIColor : Color.White;
|
||||
string characterRichString = $"‖color:{nameColor.R},{nameColor.G},{nameColor.B}‖{name}‖color:end‖";
|
||||
|
||||
LocalizedString text = string.Empty;
|
||||
if (from == null && to != null)
|
||||
{
|
||||
text = TextManager.GetWithVariables("crewwallet.requestbanktoselfvote",
|
||||
("[requester]", characterRichString),
|
||||
("[amount]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", amount)));
|
||||
}
|
||||
else if (from != null && to == null)
|
||||
{
|
||||
text = TextManager.GetWithVariables("crewwallet.requestselftobankvote",
|
||||
("[requester]", characterRichString),
|
||||
("[amount]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", amount)));
|
||||
}
|
||||
else
|
||||
{
|
||||
//not supported atm: clients can only requests transfers between their own wallet and the bank
|
||||
LocalizedString bankName = TextManager.Get("crewwallet.bank");
|
||||
text = TextManager.GetWithVariables("crewwallet.requesttransfervote",
|
||||
("[requester]", characterRichString),
|
||||
("[player1]", from?.Character == null ? bankName : from.Character.Name),
|
||||
("[player2]", to?.Character == null ? bankName : to.Character.Name),
|
||||
("[amount]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", amount)));
|
||||
}
|
||||
|
||||
votingOnText = RichString.Rich(text);
|
||||
}
|
||||
private void SendMoneyTransferVoteEndMessage(Client from, Client to, int amount)
|
||||
{
|
||||
GameMain.NetworkMember.AddChatMessage(GetMoneyTransferVoteResultMessage(from, to, amount, yesVotes, noVotes, votePassed).Value, ChatMessageType.Server);
|
||||
}
|
||||
|
||||
public static LocalizedString GetMoneyTransferVoteResultMessage(Client from, Client to, int transferAmount, int yesVoteCount, int noVoteCount, bool votePassed)
|
||||
{
|
||||
LocalizedString result = string.Empty;
|
||||
if (from == null && to != null)
|
||||
{
|
||||
result = TextManager.GetWithVariables(votePassed ? "crewwallet.banktoplayer.votepassed" : "crewwallet.banktoplayer.votefailed",
|
||||
("[playername]", to.Name),
|
||||
("[amount]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", transferAmount)),
|
||||
("[yesvotecount]", yesVoteCount.ToString()),
|
||||
("[novotecount]", noVoteCount.ToString()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public void Remove()
|
||||
{
|
||||
if (frame != null)
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
public Shape shape;
|
||||
public string tooltip;
|
||||
public LocalizedString tooltip;
|
||||
public bool showTooltip = true;
|
||||
public Rectangle DrawRect => new Rectangle((int)(DrawPos.X - (float)size / 2), (int)(DrawPos.Y - (float)size / 2), size, size);
|
||||
public Rectangle InputRect
|
||||
@@ -42,7 +42,7 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
public bool isFilled;
|
||||
public int inputAreaMargin;
|
||||
public Color color = GUI.Style.Red;
|
||||
public Color color = GUIStyle.Red;
|
||||
public Color? secondaryColor;
|
||||
public Color textColor = Color.White;
|
||||
public Color textBackgroundColor = Color.Black * 0.5f;
|
||||
@@ -183,7 +183,7 @@ namespace Barotrauma
|
||||
}
|
||||
if (IsSelected)
|
||||
{
|
||||
if (showTooltip && !string.IsNullOrEmpty(tooltip))
|
||||
if (showTooltip && !tooltip.IsNullOrEmpty())
|
||||
{
|
||||
var offset = tooltipOffset ?? new Vector2(size, -size / 2f);
|
||||
GUI.DrawString(spriteBatch, DrawPos + offset, tooltip, textColor, textBackgroundColor);
|
||||
|
||||
@@ -20,8 +20,8 @@ namespace Barotrauma
|
||||
AbsoluteSpacing = GUI.IntScale(15)
|
||||
};
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), TextManager.Get("statisticsconsentheader"), font: GUI.SubHeadingFont, textColor: Color.White);
|
||||
var mainText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), TextManager.Get("statisticsconsenttext"), wrap: true, parseRichText: true);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), TextManager.Get("statisticsconsentheader"), font: GUIStyle.SubHeadingFont, textColor: Color.White);
|
||||
var mainText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), RichString.Rich(TextManager.Get("statisticsconsenttext")), wrap: true);
|
||||
|
||||
foreach (var data in mainText.RichTextData)
|
||||
{
|
||||
@@ -93,7 +93,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (child is GUITextBlock textBlock)
|
||||
{
|
||||
textBlock.TextScale = MathHelper.Min(1.0f, 1.0f / GameSettings.TextScale);
|
||||
textBlock.TextScale = MathHelper.Min(1.0f, 1.0f / GameSettings.CurrentConfig.Graphics.TextScale);
|
||||
textBlock.RectTransform.MinSize = new Point(0, (int)textBlock.TextSize.Y);
|
||||
textBlock.RectTransform.MaxSize = new Point(int.MaxValue, (int)textBlock.TextSize.Y);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ using Barotrauma.Tutorials;
|
||||
using Barotrauma.Media;
|
||||
using Barotrauma.Extensions;
|
||||
using System.Threading.Tasks;
|
||||
using Barotrauma.Transition;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -47,8 +48,17 @@ namespace Barotrauma
|
||||
public static MainMenuScreen MainMenuScreen;
|
||||
|
||||
public static NetLobbyScreen NetLobbyScreen;
|
||||
public static ModDownloadScreen ModDownloadScreen;
|
||||
|
||||
public static void ResetNetLobbyScreen()
|
||||
{
|
||||
NetLobbyScreen?.Release();
|
||||
NetLobbyScreen = new NetLobbyScreen();
|
||||
ModDownloadScreen?.Release();
|
||||
ModDownloadScreen = new ModDownloadScreen();
|
||||
}
|
||||
|
||||
public static ServerListScreen ServerListScreen;
|
||||
public static SteamWorkshopScreen SteamWorkshopScreen;
|
||||
|
||||
public static SubEditorScreen SubEditorScreen;
|
||||
public static TestScreen TestScreen;
|
||||
@@ -66,19 +76,7 @@ namespace Barotrauma
|
||||
|
||||
public static Thread MainThread { get; private set; }
|
||||
|
||||
private static ContentPackage vanillaContent;
|
||||
public static ContentPackage VanillaContent
|
||||
{
|
||||
get
|
||||
{
|
||||
if (vanillaContent == null)
|
||||
{
|
||||
// TODO: Dynamic method for defining and finding the vanilla content package.
|
||||
vanillaContent = ContentPackage.CorePackages.SingleOrDefault(cp => Path.GetFileName(cp.Path).Equals("vanilla 0.9.xml", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
return vanillaContent;
|
||||
}
|
||||
}
|
||||
public static ContentPackage VanillaContent => ContentPackageManager.VanillaCorePackage;
|
||||
|
||||
private static GameSession gameSession;
|
||||
public static GameSession GameSession
|
||||
@@ -96,7 +94,6 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
public static ParticleManager ParticleManager;
|
||||
public static DecalManager DecalManager;
|
||||
|
||||
private static World world;
|
||||
public static World World
|
||||
@@ -112,10 +109,8 @@ namespace Barotrauma
|
||||
public static LoadingScreen TitleScreen;
|
||||
private bool loadingScreenOpen;
|
||||
|
||||
public static GameSettings Config;
|
||||
|
||||
private CoroutineHandle loadingCoroutine;
|
||||
private bool hasLoaded;
|
||||
public bool HasLoaded { get; private set; }
|
||||
|
||||
private readonly GameTime fixedTime;
|
||||
|
||||
@@ -234,11 +229,11 @@ namespace Barotrauma
|
||||
throw new Exception("Content folder not found. If you are trying to compile the game from the source code and own a legal copy of the game, you can copy the Content folder from the game's files to BarotraumaShared/Content.");
|
||||
}
|
||||
|
||||
Config = new GameSettings();
|
||||
|
||||
Lua = new LuaSetup();
|
||||
|
||||
Md5Hash.LoadCache();
|
||||
GameSettings.Init();
|
||||
|
||||
Md5Hash.Cache.Load();
|
||||
|
||||
ConsoleArguments = args;
|
||||
|
||||
@@ -294,24 +289,42 @@ namespace Barotrauma
|
||||
|
||||
public void ApplyGraphicsSettings()
|
||||
{
|
||||
GraphicsWidth = Config.GraphicsWidth;
|
||||
GraphicsHeight = Config.GraphicsHeight;
|
||||
switch (Config.WindowMode)
|
||||
void updateConfig()
|
||||
{
|
||||
var config = GameSettings.CurrentConfig;
|
||||
config.Graphics.Width = GraphicsWidth;
|
||||
config.Graphics.Height = GraphicsHeight;
|
||||
GameSettings.SetCurrentConfig(config);
|
||||
}
|
||||
|
||||
GraphicsWidth = GameSettings.CurrentConfig.Graphics.Width;
|
||||
GraphicsHeight = GameSettings.CurrentConfig.Graphics.Height;
|
||||
|
||||
if (GraphicsWidth <= 0 || GraphicsHeight <= 0)
|
||||
{
|
||||
GraphicsWidth = GraphicsDevice.DisplayMode.Width;
|
||||
GraphicsHeight = GraphicsDevice.DisplayMode.Height;
|
||||
updateConfig();
|
||||
}
|
||||
|
||||
switch (GameSettings.CurrentConfig.Graphics.DisplayMode)
|
||||
{
|
||||
case WindowMode.BorderlessWindowed:
|
||||
GraphicsWidth = GraphicsDevice.DisplayMode.Width;
|
||||
GraphicsHeight = GraphicsDevice.DisplayMode.Height;
|
||||
updateConfig();
|
||||
break;
|
||||
case WindowMode.Windowed:
|
||||
GraphicsWidth = Math.Min(GraphicsDevice.DisplayMode.Width, GraphicsWidth);
|
||||
GraphicsHeight = Math.Min(GraphicsDevice.DisplayMode.Height, GraphicsHeight);
|
||||
updateConfig();
|
||||
break;
|
||||
}
|
||||
GraphicsDeviceManager.GraphicsProfile = GfxProfile;
|
||||
GraphicsDeviceManager.PreferredBackBufferFormat = SurfaceFormat.Color;
|
||||
GraphicsDeviceManager.PreferMultiSampling = false;
|
||||
GraphicsDeviceManager.SynchronizeWithVerticalRetrace = Config.VSyncEnabled;
|
||||
SetWindowMode(Config.WindowMode);
|
||||
GraphicsDeviceManager.SynchronizeWithVerticalRetrace = GameSettings.CurrentConfig.Graphics.VSync;
|
||||
SetWindowMode(GameSettings.CurrentConfig.Graphics.DisplayMode);
|
||||
|
||||
defaultViewport = GraphicsDevice.Viewport;
|
||||
|
||||
@@ -321,8 +334,8 @@ namespace Barotrauma
|
||||
public void SetWindowMode(WindowMode windowMode)
|
||||
{
|
||||
WindowMode = windowMode;
|
||||
GraphicsDeviceManager.HardwareModeSwitch = Config.WindowMode != WindowMode.BorderlessWindowed;
|
||||
GraphicsDeviceManager.IsFullScreen = Config.WindowMode == WindowMode.Fullscreen || Config.WindowMode == WindowMode.BorderlessWindowed;
|
||||
GraphicsDeviceManager.HardwareModeSwitch = windowMode != WindowMode.BorderlessWindowed;
|
||||
GraphicsDeviceManager.IsFullScreen = windowMode == WindowMode.Fullscreen || windowMode == WindowMode.BorderlessWindowed;
|
||||
Window.IsBorderless = !GraphicsDeviceManager.HardwareModeSwitch;
|
||||
|
||||
GraphicsDeviceManager.PreferredBackBufferWidth = GraphicsWidth;
|
||||
@@ -394,7 +407,7 @@ namespace Barotrauma
|
||||
loadingScreenOpen = true;
|
||||
TitleScreen = new LoadingScreen(GraphicsDevice)
|
||||
{
|
||||
WaitForLanguageSelection = Config.ShowLanguageSelectionPrompt
|
||||
WaitForLanguageSelection = GameSettings.CurrentConfig.Language == LanguageIdentifier.None
|
||||
};
|
||||
|
||||
bool canLoadInSeparateThread = true;
|
||||
@@ -411,27 +424,31 @@ namespace Barotrauma
|
||||
|
||||
private IEnumerable<CoroutineStatus> Load(bool isSeparateThread)
|
||||
{
|
||||
if (GameSettings.VerboseLogging)
|
||||
if (GameSettings.CurrentConfig.VerboseLogging)
|
||||
{
|
||||
DebugConsole.NewMessage("LOADING COROUTINE", Color.Lime);
|
||||
}
|
||||
|
||||
while (TitleScreen.WaitForLanguageSelection)
|
||||
ContentPackageManager.LoadVanillaFileList();
|
||||
|
||||
if (TitleScreen.WaitForLanguageSelection)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
ContentPackageManager.VanillaCorePackage.LoadFilesOfType<TextFile>();
|
||||
TitleScreen.AvailableLanguages = TextManager.AvailableLanguages.ToArray();
|
||||
while (TitleScreen.WaitForLanguageSelection)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
ContentPackageManager.VanillaCorePackage.UnloadFilesOfType<TextFile>();
|
||||
}
|
||||
|
||||
SoundManager = new Sounds.SoundManager();
|
||||
SoundManager.SetCategoryGainMultiplier("default", Config.SoundVolume, 0);
|
||||
SoundManager.SetCategoryGainMultiplier("ui", Config.SoundVolume, 0);
|
||||
SoundManager.SetCategoryGainMultiplier("waterambience", Config.SoundVolume, 0);
|
||||
SoundManager.SetCategoryGainMultiplier("music", Config.MusicVolume, 0);
|
||||
SoundManager.SetCategoryGainMultiplier("voip", Math.Min(Config.VoiceChatVolume, 1.0f), 0);
|
||||
SoundManager.ApplySettings();
|
||||
|
||||
if (Config.EnableSplashScreen && !ConsoleArguments.Contains("-skipintro"))
|
||||
if (GameSettings.CurrentConfig.EnableSplashScreen && !ConsoleArguments.Contains("-skipintro"))
|
||||
{
|
||||
var pendingSplashScreens = TitleScreen.PendingSplashScreens;
|
||||
float baseVolume = MathHelper.Clamp(Config.SoundVolume * 2.0f, 0.0f, 1.0f);
|
||||
float baseVolume = MathHelper.Clamp(GameSettings.CurrentConfig.Audio.SoundVolume * 2.0f, 0.0f, 1.0f);
|
||||
pendingSplashScreens?.Enqueue(new LoadingScreen.PendingSplashScreen("Content/SplashScreens/Splash_UTG.webm", baseVolume * 0.5f));
|
||||
pendingSplashScreens?.Enqueue(new LoadingScreen.PendingSplashScreen("Content/SplashScreens/Splash_FF.webm", baseVolume));
|
||||
pendingSplashScreens?.Enqueue(new LoadingScreen.PendingSplashScreen("Content/SplashScreens/Splash_Daedalic.webm", baseVolume * 0.1f));
|
||||
@@ -447,153 +464,57 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
GUI.Init(Window, Config.AllEnabledPackages, GraphicsDevice);
|
||||
GUI.Init();
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
UgcTransition.Prepare();
|
||||
var contentPackageLoadRoutine = ContentPackageManager.Init();
|
||||
foreach (var progress in contentPackageLoadRoutine)
|
||||
{
|
||||
const float min = 1f, max = 70f;
|
||||
TitleScreen.LoadState = MathHelper.Lerp(min, max, progress.Value);
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
TextManager.VerifyLanguageAvailable();
|
||||
|
||||
DebugConsole.Init();
|
||||
|
||||
if (Config.AutoUpdateWorkshopItems)
|
||||
{
|
||||
Config.WaitingForAutoUpdate = true;
|
||||
TaskPool.Add("AutoUpdateWorkshopItemsAsync",
|
||||
SteamManager.AutoUpdateWorkshopItemsAsync(), (task) =>
|
||||
{
|
||||
if (!task.TryGetResult(out bool result)) { return; }
|
||||
|
||||
Config.WaitingForAutoUpdate = false;
|
||||
});
|
||||
|
||||
while (Config.WaitingForAutoUpdate) { yield return CoroutineStatus.Running; }
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
if (Config.ModBreakerMode)
|
||||
{
|
||||
Config.SelectCorePackage(ContentPackage.CorePackages.GetRandom());
|
||||
foreach (var regularPackage in ContentPackage.RegularPackages)
|
||||
{
|
||||
if (Rand.Range(0.0, 1.0) <= 0.5)
|
||||
{
|
||||
Config.EnableRegularPackage(regularPackage);
|
||||
}
|
||||
else
|
||||
{
|
||||
Config.DisableRegularPackage(regularPackage);
|
||||
}
|
||||
}
|
||||
ContentPackage.SortContentPackages(p =>
|
||||
{
|
||||
return Rand.Int(int.MaxValue);
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
if (Config.AllEnabledPackages.None())
|
||||
{
|
||||
DebugConsole.Log("No content packages selected");
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.Log("Selected content packages: " + string.Join(", ", Config.AllEnabledPackages.Select(cp => cp.Name)));
|
||||
}
|
||||
ContentPackageManager.LogEnabledRegularPackageErrors();
|
||||
|
||||
#if !DEBUG && !OSX
|
||||
GameAnalyticsManager.InitIfConsented();
|
||||
#endif
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
Debug.WriteLine("sounds");
|
||||
|
||||
int i = 0;
|
||||
foreach (CoroutineStatus status in SoundPlayer.Init())
|
||||
{
|
||||
if (status == CoroutineStatus.Success) break;
|
||||
|
||||
i++;
|
||||
TitleScreen.LoadState = SoundPlayer.SoundCount == 0 ?
|
||||
1.0f :
|
||||
Math.Min(40.0f * i / Math.Max(SoundPlayer.SoundCount, 1), 40.0f);
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
TitleScreen.LoadState = 40.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
LightManager = new Lights.LightManager(base.GraphicsDevice, Content);
|
||||
|
||||
TitleScreen.LoadState = 41.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
GUI.LoadContent();
|
||||
TitleScreen.LoadState = 42.0f;
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
TaskPool.Add("InitRelayNetworkAccess", SteamManager.InitRelayNetworkAccess(), (t) => { });
|
||||
|
||||
FactionPrefab.LoadFactions();
|
||||
NPCSet.LoadSets();
|
||||
CharacterPrefab.LoadAll();
|
||||
MissionPrefab.Init();
|
||||
TraitorMissionPrefab.Init();
|
||||
MapEntityPrefab.Init();
|
||||
Tutorials.Tutorial.Init();
|
||||
MapGenerationParams.Init();
|
||||
LevelGenerationParams.LoadPresets();
|
||||
CaveGenerationParams.LoadPresets();
|
||||
OutpostGenerationParams.LoadPresets();
|
||||
WreckAIConfig.LoadAll();
|
||||
EventSet.LoadPrefabs();
|
||||
ItemPrefab.LoadAll(GetFilesOfType(ContentType.Item));
|
||||
AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions));
|
||||
SkillSettings.Load(GetFilesOfType(ContentType.SkillSettings));
|
||||
TalentPrefab.LoadAll(GetFilesOfType(ContentType.Talents));
|
||||
TalentTree.LoadAll(GetFilesOfType(ContentType.TalentTrees));
|
||||
Order.Init();
|
||||
EventManagerSettings.Init();
|
||||
BallastFloraPrefab.LoadAll(GetFilesOfType(ContentType.MapCreature));
|
||||
HintManager.Init();
|
||||
TitleScreen.LoadState = 50.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
StructurePrefab.LoadAll(GetFilesOfType(ContentType.Structure));
|
||||
TitleScreen.LoadState = 55.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
UpgradePrefab.LoadAll(GetFilesOfType(ContentType.UpgradeModules));
|
||||
TitleScreen.LoadState = 56.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
JobPrefab.LoadAll(GetFilesOfType(ContentType.Jobs));
|
||||
CorpsePrefab.LoadAll(GetFilesOfType(ContentType.Corpses));
|
||||
|
||||
NPCConversation.LoadAll(GetFilesOfType(ContentType.NPCConversations));
|
||||
|
||||
ItemAssemblyPrefab.LoadAll();
|
||||
TitleScreen.LoadState = 60.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
CoreEntityPrefab.InitCorePrefabs();
|
||||
GameModePreset.Init();
|
||||
|
||||
SaveUtil.DeleteDownloadedSubs();
|
||||
SubmarineInfo.RefreshSavedSubs();
|
||||
|
||||
TitleScreen.LoadState = 65.0f;
|
||||
TitleScreen.LoadState = 75.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
GameScreen = new GameScreen(GraphicsDeviceManager.GraphicsDevice, Content);
|
||||
|
||||
TitleScreen.LoadState = 68.0f;
|
||||
ParticleManager = new ParticleManager(GameScreen.Cam);
|
||||
LightManager = new Lights.LightManager(base.GraphicsDevice, Content);
|
||||
|
||||
TitleScreen.LoadState = 80.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
MainMenuScreen = new MainMenuScreen(this);
|
||||
ServerListScreen = new ServerListScreen();
|
||||
|
||||
TitleScreen.LoadState = 70.0f;
|
||||
TitleScreen.LoadState = 85.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
#if USE_STEAM
|
||||
SteamWorkshopScreen = new SteamWorkshopScreen();
|
||||
if (SteamManager.IsInitialized)
|
||||
{
|
||||
Steamworks.SteamFriends.OnGameRichPresenceJoinRequested += OnInvitedToGame;
|
||||
@@ -603,25 +524,25 @@ namespace Barotrauma
|
||||
{
|
||||
//check the achievements too, so we don't consider people who've played the game before this "gamelaunchcount" stat was added as being 1st-time-players
|
||||
//(people who have played previous versions, but not unlocked any achievements, will be incorrectly considered 1st-time-players, but that should be a small enough group to not skew the statistics)
|
||||
if (!achievements.Any() && SteamManager.GetStatInt("gamelaunchcount") <= 0)
|
||||
if (!achievements.Any() && SteamManager.GetStatInt("gamelaunchcount".ToIdentifier()) <= 0)
|
||||
{
|
||||
IsFirstLaunch = true;
|
||||
GameAnalyticsManager.AddDesignEvent("FirstLaunch");
|
||||
}
|
||||
}
|
||||
SteamManager.IncrementStat("gamelaunchcount", 1);
|
||||
SteamManager.IncrementStat("gamelaunchcount".ToIdentifier(), 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
SubEditorScreen = new SubEditorScreen();
|
||||
TestScreen = new TestScreen();
|
||||
|
||||
TitleScreen.LoadState = 75.0f;
|
||||
TitleScreen.LoadState = 90.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
ParticleEditorScreen = new ParticleEditorScreen();
|
||||
|
||||
TitleScreen.LoadState = 80.0f;
|
||||
TitleScreen.LoadState = 95.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
LevelEditorScreen = new LevelEditorScreen();
|
||||
@@ -632,31 +553,20 @@ namespace Barotrauma
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
TitleScreen.LoadState = 85.0f;
|
||||
ParticleManager = new ParticleManager(GameScreen.Cam);
|
||||
ParticleManager.LoadPrefabs();
|
||||
TitleScreen.LoadState = 88.0f;
|
||||
LevelObjectPrefab.LoadAll();
|
||||
|
||||
TitleScreen.LoadState = 90.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
DecalManager = new DecalManager();
|
||||
LocationType.Init();
|
||||
MainMenuScreen.Select();
|
||||
|
||||
foreach (string steamError in SteamManager.InitializationErrors)
|
||||
foreach (Identifier steamError in SteamManager.InitializationErrors)
|
||||
{
|
||||
new GUIMessageBox(TextManager.Get("Error"), TextManager.Get(steamError));
|
||||
}
|
||||
|
||||
TitleScreen.LoadState = 100.0f;
|
||||
hasLoaded = true;
|
||||
if (GameSettings.VerboseLogging)
|
||||
HasLoaded = true;
|
||||
if (GameSettings.CurrentConfig.VerboseLogging)
|
||||
{
|
||||
DebugConsole.NewMessage("LOADING COROUTINE FINISHED", Color.Lime);
|
||||
}
|
||||
yield return CoroutineStatus.Success;
|
||||
yield return CoroutineStatus.Success;
|
||||
|
||||
}
|
||||
|
||||
@@ -674,23 +584,6 @@ namespace Barotrauma
|
||||
MainThread = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the file paths of all files of the given type in the content packages.
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="searchAllContentPackages">If true, also returns files in content packages that are installed but not currently selected.</param>
|
||||
public IEnumerable<ContentFile> GetFilesOfType(ContentType type, bool searchAllContentPackages = false)
|
||||
{
|
||||
if (searchAllContentPackages)
|
||||
{
|
||||
return ContentPackage.GetFilesOfType(ContentPackage.AllPackages, type);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ContentPackage.GetFilesOfType(Config.AllEnabledPackages, type);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnInvitedToGame(Steamworks.Friend friend, string connectCommand) => OnInvitedToGame(connectCommand);
|
||||
|
||||
public void OnInvitedToGame(string connectCommand)
|
||||
@@ -741,7 +634,7 @@ namespace Barotrauma
|
||||
|
||||
if (SoundManager != null)
|
||||
{
|
||||
if (WindowActive || !Config.MuteOnFocusLost)
|
||||
if (WindowActive || !GameSettings.CurrentConfig.Audio.MuteOnFocusLost)
|
||||
{
|
||||
SoundManager.ListenerGain = SoundManager.CompressionDynamicRangeGain;
|
||||
}
|
||||
@@ -790,29 +683,30 @@ namespace Barotrauma
|
||||
CancelQuickStart = !CancelQuickStart;
|
||||
}
|
||||
|
||||
if (TitleScreen.LoadState >= 100.0f && !TitleScreen.PlayingSplashScreen && (Config.AutomaticQuickStartEnabled || Config.AutomaticCampaignLoadEnabled || Config.TestScreenEnabled) && FirstLoad && !CancelQuickStart)
|
||||
if (TitleScreen.LoadState >= 100.0f && !TitleScreen.PlayingSplashScreen &&
|
||||
(GameSettings.CurrentConfig.AutomaticQuickStartEnabled ||
|
||||
GameSettings.CurrentConfig.AutomaticCampaignLoadEnabled ||
|
||||
GameSettings.CurrentConfig.TestScreenEnabled) && FirstLoad && !CancelQuickStart)
|
||||
{
|
||||
loadingScreenOpen = false;
|
||||
FirstLoad = false;
|
||||
|
||||
if (Config.TestScreenEnabled)
|
||||
if (GameSettings.CurrentConfig.TestScreenEnabled)
|
||||
{
|
||||
TestScreen.Select();
|
||||
}
|
||||
else if (Config.AutomaticQuickStartEnabled)
|
||||
}
|
||||
else if (GameSettings.CurrentConfig.AutomaticQuickStartEnabled)
|
||||
{
|
||||
MainMenuScreen.QuickStart();
|
||||
}
|
||||
else if (Config.AutomaticCampaignLoadEnabled)
|
||||
else if (GameSettings.CurrentConfig.AutomaticCampaignLoadEnabled)
|
||||
{
|
||||
IEnumerable<string> saveFiles = SaveUtil.GetSaveFiles(SaveUtil.SaveType.Singleplayer);
|
||||
|
||||
var saveFiles = SaveUtil.GetSaveFiles(SaveUtil.SaveType.Singleplayer);
|
||||
if (saveFiles.Count() > 0)
|
||||
{
|
||||
saveFiles = saveFiles.OrderBy(file => File.GetLastWriteTime(file));
|
||||
try
|
||||
{
|
||||
SaveUtil.LoadGame(saveFiles.Last());
|
||||
SaveUtil.LoadGame(saveFiles.OrderBy(file => file.SaveTime).Last().FilePath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -826,12 +720,12 @@ namespace Barotrauma
|
||||
|
||||
NetworkMember?.Update((float)Timing.Step);
|
||||
|
||||
if (!hasLoaded && !CoroutineManager.IsCoroutineRunning(loadingCoroutine))
|
||||
if (!HasLoaded && !CoroutineManager.IsCoroutineRunning(loadingCoroutine))
|
||||
{
|
||||
throw new LoadingException(loadingCoroutine.Exception);
|
||||
}
|
||||
}
|
||||
else if (hasLoaded)
|
||||
else if (HasLoaded)
|
||||
{
|
||||
if (ConnectLobby != 0)
|
||||
{
|
||||
@@ -858,7 +752,7 @@ namespace Barotrauma
|
||||
GameMain.MainMenuScreen.Select();
|
||||
}
|
||||
UInt64 serverSteamId = SteamManager.SteamIDStringToUInt64(ConnectEndpoint);
|
||||
Client = new GameClient(Config.PlayerName,
|
||||
Client = new GameClient(MultiplayerPreferences.Instance.PlayerName.FallbackNullOrEmpty(SteamManager.GetUsername()),
|
||||
serverSteamId != 0 ? null : ConnectEndpoint,
|
||||
serverSteamId,
|
||||
string.IsNullOrWhiteSpace(ConnectName) ? ConnectEndpoint : ConnectName);
|
||||
@@ -892,9 +786,9 @@ namespace Barotrauma
|
||||
{
|
||||
GUIMessageBox.MessageBoxes.Remove(GUIMessageBox.VisibleBox);
|
||||
}
|
||||
else if (Tutorial.Initialized && Tutorial.ContentRunning)
|
||||
else if (GameSession?.GameMode is TutorialMode tutorialMode && tutorialMode.Tutorial.ContentRunning)
|
||||
{
|
||||
(GameSession.GameMode as TutorialMode).Tutorial.CloseActiveContentGUI();
|
||||
tutorialMode.Tutorial.CloseActiveContentGUI();
|
||||
}
|
||||
else if (GameSession.IsTabMenuOpen)
|
||||
{
|
||||
@@ -939,8 +833,11 @@ namespace Barotrauma
|
||||
#endif
|
||||
|
||||
GUI.ClearUpdateList();
|
||||
Paused = (DebugConsole.IsOpen || GUI.PauseMenuOpen || GUI.SettingsMenuOpen || Tutorial.ContentRunning || DebugConsole.Paused) &&
|
||||
(NetworkMember == null || !NetworkMember.GameStarted);
|
||||
Paused =
|
||||
(DebugConsole.IsOpen || DebugConsole.Paused ||
|
||||
GUI.PauseMenuOpen || GUI.SettingsMenuOpen ||
|
||||
(GameSession?.GameMode is TutorialMode tutoMode && tutoMode.Tutorial.ContentRunning)) &&
|
||||
(NetworkMember == null || !NetworkMember.GameStarted);
|
||||
if (GameSession?.GameMode != null && GameSession.GameMode.Paused)
|
||||
{
|
||||
Paused = true;
|
||||
@@ -948,7 +845,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
#if !DEBUG
|
||||
if (NetworkMember == null && !WindowActive && !Paused && true && Config.PauseOnFocusLost &&
|
||||
if (NetworkMember == null && !WindowActive && !Paused && true && GameSettings.CurrentConfig.PauseOnFocusLost &&
|
||||
Screen.Selected != MainMenuScreen && Screen.Selected != ServerListScreen && Screen.Selected != NetLobbyScreen &&
|
||||
Screen.Selected != SubEditorScreen && Screen.Selected != LevelEditorScreen)
|
||||
{
|
||||
@@ -973,9 +870,9 @@ namespace Barotrauma
|
||||
{
|
||||
Screen.Selected.Update(Timing.Step);
|
||||
}
|
||||
else if (Tutorial.Initialized && Tutorial.ContentRunning)
|
||||
else if (GameSession?.GameMode is TutorialMode tutorialMode && tutorialMode.Tutorial.ContentRunning)
|
||||
{
|
||||
(GameSession.GameMode as TutorialMode).Update((float)Timing.Step);
|
||||
tutorialMode.Update((float)Timing.Step);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -992,6 +889,27 @@ namespace Barotrauma
|
||||
NetworkMember?.Update((float)Timing.Step);
|
||||
|
||||
GUI.Update((float)Timing.Step);
|
||||
|
||||
#if DEBUG
|
||||
if (DebugDraw && GUI.MouseOn != null && PlayerInput.IsCtrlDown() && PlayerInput.KeyHit(Keys.G))
|
||||
{
|
||||
List<GUIComponent> hierarchy = new List<GUIComponent>();
|
||||
var currComponent = GUI.MouseOn;
|
||||
while (currComponent != null)
|
||||
{
|
||||
hierarchy.Add(currComponent);
|
||||
currComponent = currComponent.Parent;
|
||||
}
|
||||
DebugConsole.NewMessage("*********************");
|
||||
foreach (var component in hierarchy)
|
||||
{
|
||||
if (component is { MouseRect: var mouseRect, Rect: var rect })
|
||||
{
|
||||
DebugConsole.NewMessage($"{component.GetType().Name} {component.Style?.Name ?? "[null]"} {rect.Bottom} {mouseRect.Bottom}", mouseRect!=rect ? Color.Lime : Color.Red);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
CoroutineManager.Update((float)Timing.Step, Paused ? 0.0f : (float)Timing.Step);
|
||||
@@ -1042,7 +960,7 @@ namespace Barotrauma
|
||||
if (Timing.FrameLimit > 0)
|
||||
{
|
||||
double step = 1.0 / Timing.FrameLimit;
|
||||
while (!Config.VSyncEnabled && sw.Elapsed.TotalSeconds + deltaTime < step)
|
||||
while (!GameSettings.CurrentConfig.Graphics.VSync && sw.Elapsed.TotalSeconds + deltaTime < step)
|
||||
{
|
||||
Thread.Sleep(1);
|
||||
}
|
||||
@@ -1054,7 +972,7 @@ namespace Barotrauma
|
||||
{
|
||||
TitleScreen.Draw(spriteBatch, base.GraphicsDevice, (float)deltaTime);
|
||||
}
|
||||
else if (hasLoaded)
|
||||
else if (HasLoaded)
|
||||
{
|
||||
Screen.Selected.Draw(deltaTime, base.GraphicsDevice, spriteBatch);
|
||||
}
|
||||
@@ -1062,8 +980,33 @@ namespace Barotrauma
|
||||
if (DebugDraw && GUI.MouseOn != null)
|
||||
{
|
||||
spriteBatch.Begin();
|
||||
GUI.DrawRectangle(spriteBatch, GUI.MouseOn.MouseRect, Color.Lime);
|
||||
GUI.DrawRectangle(spriteBatch, GUI.MouseOn.Rect, Color.Cyan);
|
||||
if (PlayerInput.IsCtrlDown() && PlayerInput.KeyDown(Keys.G))
|
||||
{
|
||||
List<GUIComponent> hierarchy = new List<GUIComponent>();
|
||||
var currComponent = GUI.MouseOn;
|
||||
while (currComponent != null)
|
||||
{
|
||||
hierarchy.Add(currComponent);
|
||||
currComponent = currComponent.Parent;
|
||||
}
|
||||
|
||||
Color[] colors = { Color.Lime, Color.Yellow, Color.Aqua, Color.Red };
|
||||
for (int index = 0; index < hierarchy.Count; index++)
|
||||
{
|
||||
var component = hierarchy[index];
|
||||
if (component is { MouseRect: var mouseRect, Rect: var rect })
|
||||
{
|
||||
if (mouseRect.IsEmpty) { mouseRect = rect; }
|
||||
mouseRect.Location += (index%2,(index%4)/2);
|
||||
GUI.DrawRectangle(spriteBatch, mouseRect, colors[index%4]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, GUI.MouseOn.MouseRect, Color.Lime);
|
||||
GUI.DrawRectangle(spriteBatch, GUI.MouseOn.Rect, Color.Cyan);
|
||||
}
|
||||
spriteBatch.End();
|
||||
}
|
||||
|
||||
@@ -1078,7 +1021,7 @@ namespace Barotrauma
|
||||
if (showVerificationPrompt)
|
||||
{
|
||||
string text = (Screen.Selected is CharacterEditor.CharacterEditorScreen || Screen.Selected is SubEditorScreen) ? "PauseMenuQuitVerificationEditor" : "PauseMenuQuitVerification";
|
||||
var msgBox = new GUIMessageBox("", TextManager.Get(text), new string[] { TextManager.Get("Yes"), TextManager.Get("Cancel") })
|
||||
var msgBox = new GUIMessageBox("", TextManager.Get(text), new LocalizedString[] { TextManager.Get("Yes"), TextManager.Get("Cancel") })
|
||||
{
|
||||
UserData = "verificationprompt"
|
||||
};
|
||||
@@ -1106,9 +1049,9 @@ namespace Barotrauma
|
||||
// Update store stock when saving and quitting in an outpost (normally updated when CampaignMode.End() is called)
|
||||
if (GameSession?.Campaign is SinglePlayerCampaign spCampaign && Level.IsLoadedOutpost && spCampaign.Map?.CurrentLocation != null && spCampaign.CargoManager != null)
|
||||
{
|
||||
spCampaign.Map.CurrentLocation.AddToStock(spCampaign.CargoManager.SoldItems);
|
||||
spCampaign.Map.CurrentLocation.AddStock(spCampaign.CargoManager.SoldItems);
|
||||
spCampaign.CargoManager.ClearSoldItemsProjSpecific();
|
||||
spCampaign.Map.CurrentLocation.RemoveFromStock(spCampaign.CargoManager.PurchasedItems);
|
||||
spCampaign.Map.CurrentLocation.RemoveStock(spCampaign.CargoManager.PurchasedItems);
|
||||
}
|
||||
|
||||
SaveUtil.SaveGame(GameSession.SavePath);
|
||||
@@ -1126,18 +1069,18 @@ namespace Barotrauma
|
||||
{
|
||||
double roundDuration = Timing.TotalTime - GameSession.RoundStartTime;
|
||||
GameAnalyticsManager.AddProgressionEvent(GameAnalyticsManager.ProgressionStatus.Fail,
|
||||
GameSession.GameMode?.Preset.Identifier ?? "none",
|
||||
GameSession.GameMode?.Preset.Identifier.Value ?? "none",
|
||||
roundDuration);
|
||||
string eventId = "QuitRound:" + (GameSession.GameMode?.Preset.Identifier ?? "none") + ":";
|
||||
string eventId = "QuitRound:" + (GameSession.GameMode?.Preset.Identifier.Value ?? "none") + ":";
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "EventManager:CurrentIntensity", GameSession.EventManager.CurrentIntensity);
|
||||
foreach (var activeEvent in GameSession.EventManager.ActiveEvents)
|
||||
{
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + "EventManager:ActiveEvents:" + activeEvent.ToString());
|
||||
}
|
||||
GameSession.LogEndRoundStats(eventId);
|
||||
if (Tutorial.Initialized)
|
||||
if (GameSession.GameMode is TutorialMode tutorialMode)
|
||||
{
|
||||
((TutorialMode)GameSession.GameMode).Tutorial?.Stop();
|
||||
tutorialMode.Tutorial?.Stop();
|
||||
}
|
||||
}
|
||||
GUIMessageBox.CloseAll();
|
||||
@@ -1150,7 +1093,7 @@ namespace Barotrauma
|
||||
public void ShowCampaignDisclaimer(Action onContinue = null)
|
||||
{
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("CampaignDisclaimerTitle"), TextManager.Get("CampaignDisclaimerText"),
|
||||
new string[] { TextManager.Get("CampaignRoadMapTitle"), TextManager.Get("OK") });
|
||||
new LocalizedString[] { TextManager.Get("CampaignRoadMapTitle"), TextManager.Get("OK") });
|
||||
|
||||
msgBox.Buttons[0].OnClicked = (btn, userdata) =>
|
||||
{
|
||||
@@ -1161,8 +1104,10 @@ namespace Barotrauma
|
||||
msgBox.Buttons[1].OnClicked += msgBox.Close;
|
||||
msgBox.Buttons[1].OnClicked += (_, __) => { onContinue?.Invoke(); return true; };
|
||||
|
||||
Config.CampaignDisclaimerShown = true;
|
||||
Config.SaveNewPlayerConfig();
|
||||
var config = GameSettings.CurrentConfig;
|
||||
config.CampaignDisclaimerShown = true;
|
||||
GameSettings.SetCurrentConfig(config);
|
||||
GameSettings.SaveCurrentConfig();
|
||||
}
|
||||
|
||||
public void ShowEditorDisclaimer()
|
||||
@@ -1170,16 +1115,16 @@ namespace Barotrauma
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("EditorDisclaimerTitle"), TextManager.Get("EditorDisclaimerText"));
|
||||
var linkHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), msgBox.Content.RectTransform)) { Stretch = true, RelativeSpacing = 0.025f };
|
||||
linkHolder.RectTransform.MaxSize = new Point(int.MaxValue, linkHolder.Rect.Height);
|
||||
List<Pair<string, string>> links = new List<Pair<string, string>>()
|
||||
List<(LocalizedString Caption, LocalizedString Url)> links = new List<(LocalizedString, LocalizedString)>()
|
||||
{
|
||||
new Pair<string, string>(TextManager.Get("EditorDisclaimerWikiLink"), TextManager.Get("EditorDisclaimerWikiUrl")),
|
||||
new Pair<string, string>(TextManager.Get("EditorDisclaimerDiscordLink"), TextManager.Get("EditorDisclaimerDiscordUrl")),
|
||||
(TextManager.Get("EditorDisclaimerWikiLink"), TextManager.Get("EditorDisclaimerWikiUrl")),
|
||||
(TextManager.Get("EditorDisclaimerDiscordLink"), TextManager.Get("EditorDisclaimerDiscordUrl")),
|
||||
};
|
||||
foreach (var link in links)
|
||||
{
|
||||
new GUIButton(new RectTransform(new Vector2(1.0f, 0.2f), linkHolder.RectTransform), link.First, style: "MainMenuGUIButton", textAlignment: Alignment.Left)
|
||||
new GUIButton(new RectTransform(new Vector2(1.0f, 0.2f), linkHolder.RectTransform), link.Caption, style: "MainMenuGUIButton", textAlignment: Alignment.Left)
|
||||
{
|
||||
UserData = link.Second,
|
||||
UserData = link.Url,
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
ShowOpenUrlInWebBrowserPrompt(userdata as string);
|
||||
@@ -1190,8 +1135,10 @@ namespace Barotrauma
|
||||
|
||||
msgBox.InnerFrame.RectTransform.MinSize = new Point(0,
|
||||
msgBox.InnerFrame.Rect.Height + linkHolder.Rect.Height + msgBox.Content.AbsoluteSpacing * 2 + 10);
|
||||
Config.EditorDisclaimerShown = true;
|
||||
Config.SaveNewPlayerConfig();
|
||||
var config = GameSettings.CurrentConfig;
|
||||
config.EditorDisclaimerShown = true;
|
||||
GameSettings.SetCurrentConfig(config);
|
||||
GameSettings.SaveCurrentConfig();
|
||||
}
|
||||
|
||||
public void ShowBugReporter()
|
||||
@@ -1265,7 +1212,8 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
if (GameAnalyticsManager.SendUserStatistics) { GameAnalyticsManager.ShutDown(); }
|
||||
if (GameSettings.SaveDebugConsoleLogs || GameSettings.VerboseLogging) { DebugConsole.SaveLogs(); }
|
||||
if (GameSettings.CurrentConfig.SaveDebugConsoleLogs
|
||||
|| GameSettings.CurrentConfig.VerboseLogging) { DebugConsole.SaveLogs(); }
|
||||
|
||||
base.OnExiting(sender, args);
|
||||
}
|
||||
@@ -1275,14 +1223,14 @@ namespace Barotrauma
|
||||
if (string.IsNullOrEmpty(url)) { return; }
|
||||
if (GUIMessageBox.VisibleBox?.UserData as string == "verificationprompt") { return; }
|
||||
|
||||
string text = TextManager.GetWithVariable("openlinkinbrowserprompt", "[link]", url);
|
||||
string extensionText = TextManager.Get(promptExtensionTag, returnNull: true, useEnglishAsFallBack: false);
|
||||
if (!string.IsNullOrEmpty(extensionText))
|
||||
LocalizedString text = TextManager.GetWithVariable("openlinkinbrowserprompt", "[link]", url);
|
||||
LocalizedString extensionText = TextManager.Get(promptExtensionTag);
|
||||
if (!extensionText.IsNullOrEmpty())
|
||||
{
|
||||
text += $"\n\n{extensionText}";
|
||||
}
|
||||
|
||||
var msgBox = new GUIMessageBox("", text, new string[] { TextManager.Get("Yes"), TextManager.Get("No") })
|
||||
var msgBox = new GUIMessageBox("", text, new LocalizedString[] { TextManager.Get("Yes"), TextManager.Get("No") })
|
||||
{
|
||||
UserData = "verificationprompt"
|
||||
};
|
||||
|
||||
@@ -45,28 +45,39 @@ namespace Barotrauma
|
||||
return SoldEntities.Where(se => se.Status != SoldEntity.SellStatus.Unconfirmed);
|
||||
}
|
||||
|
||||
public void SetItemsInBuyCrate(List<PurchasedItem> items)
|
||||
public void SetItemsInBuyCrate(Dictionary<Identifier, List<PurchasedItem>> items)
|
||||
{
|
||||
ItemsInBuyCrate.Clear();
|
||||
ItemsInBuyCrate.AddRange(items);
|
||||
foreach (var entry in items)
|
||||
{
|
||||
ItemsInBuyCrate.Add(entry.Key, entry.Value);
|
||||
}
|
||||
OnItemsInBuyCrateChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void SetItemsInSubSellCrate(List<PurchasedItem> items)
|
||||
public void SetItemsInSubSellCrate(Dictionary<Identifier, List<PurchasedItem>> items)
|
||||
{
|
||||
ItemsInSellFromSubCrate.Clear();
|
||||
ItemsInSellFromSubCrate.AddRange(items);
|
||||
foreach (var entry in items)
|
||||
{
|
||||
ItemsInSellFromSubCrate.Add(entry.Key, entry.Value);
|
||||
}
|
||||
OnItemsInSellFromSubCrateChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void SetSoldItems(List<SoldItem> items)
|
||||
public void SetSoldItems(Dictionary<Identifier, List<SoldItem>> items)
|
||||
{
|
||||
if (SoldItems.Count == 0 && items.Count == 0) { return; }
|
||||
|
||||
SoldItems.Clear();
|
||||
SoldItems.AddRange(items);
|
||||
foreach (var entry in items)
|
||||
{
|
||||
SoldItems.Add(entry.Key, entry.Value);
|
||||
}
|
||||
foreach (var se in SoldEntities)
|
||||
{
|
||||
if (se.Status == SoldEntity.SellStatus.Confirmed) { continue; }
|
||||
if (SoldItems.Any(si => Match(si, se, true)))
|
||||
if (SoldItems.Any(si => si.Value.Any(si => Match(si, se, true))))
|
||||
{
|
||||
se.Status = SoldEntity.SellStatus.Confirmed;
|
||||
}
|
||||
@@ -75,13 +86,16 @@ namespace Barotrauma
|
||||
se.Status = SoldEntity.SellStatus.Unconfirmed;
|
||||
}
|
||||
}
|
||||
foreach (var si in SoldItems)
|
||||
foreach (var soldItems in SoldItems.Values)
|
||||
{
|
||||
if (si.Origin != SoldItem.SellOrigin.Submarine) { continue; }
|
||||
if (!(SoldEntities.FirstOrDefault(se => se.Item == null && Match(si, se, false)) is SoldEntity soldEntityMatch)) { continue; }
|
||||
if (!(Entity.FindEntityByID(si.ID) is Item item)) { continue; }
|
||||
soldEntityMatch.SetItem(item);
|
||||
soldEntityMatch.Status = SoldEntity.SellStatus.Confirmed;
|
||||
foreach (var si in soldItems)
|
||||
{
|
||||
if (si.Origin != SoldItem.SellOrigin.Submarine) { continue; }
|
||||
if (!(SoldEntities.FirstOrDefault(se => se.Item == null && Match(si, se, false)) is SoldEntity soldEntityMatch)) { continue; }
|
||||
if (!(Entity.FindEntityByID(si.ID) is Item item)) { continue; }
|
||||
soldEntityMatch.SetItem(item);
|
||||
soldEntityMatch.Status = SoldEntity.SellStatus.Confirmed;
|
||||
}
|
||||
}
|
||||
OnSoldItemsChanged?.Invoke();
|
||||
|
||||
@@ -94,45 +108,24 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public void ModifyItemQuantityInSellCrate(ItemPrefab itemPrefab, int changeInQuantity)
|
||||
public void ModifyItemQuantityInSellCrate(Identifier storeIdentifier, ItemPrefab itemPrefab, int changeInQuantity)
|
||||
{
|
||||
var itemToSell = ItemsInSellCrate.Find(i => i.ItemPrefab == itemPrefab);
|
||||
if (itemToSell != null)
|
||||
if (GetSellCrateItem(storeIdentifier, itemPrefab) is { } item)
|
||||
{
|
||||
itemToSell.Quantity += changeInQuantity;
|
||||
if (itemToSell.Quantity < 1)
|
||||
item.Quantity += changeInQuantity;
|
||||
if (item.Quantity < 1)
|
||||
{
|
||||
ItemsInSellCrate.Remove(itemToSell);
|
||||
GetSellCrateItems(storeIdentifier)?.Remove(item);
|
||||
}
|
||||
}
|
||||
else if (changeInQuantity > 0)
|
||||
{
|
||||
itemToSell = new PurchasedItem(itemPrefab, changeInQuantity);
|
||||
ItemsInSellCrate.Add(itemToSell);
|
||||
GetSellCrateItems(storeIdentifier, create: true).Add(new PurchasedItem(itemPrefab, changeInQuantity));
|
||||
}
|
||||
OnItemsInSellCrateChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void ModifyItemQuantityInSellFromSubCrate(ItemPrefab itemPrefab, int changeInQuantity)
|
||||
{
|
||||
var itemToSell = ItemsInSellFromSubCrate.Find(i => i.ItemPrefab == itemPrefab);
|
||||
if (itemToSell != null)
|
||||
{
|
||||
itemToSell.Quantity += changeInQuantity;
|
||||
if (itemToSell.Quantity < 1)
|
||||
{
|
||||
ItemsInSellFromSubCrate.Remove(itemToSell);
|
||||
}
|
||||
}
|
||||
else if (changeInQuantity > 0)
|
||||
{
|
||||
itemToSell = new PurchasedItem(itemPrefab, changeInQuantity);
|
||||
ItemsInSellFromSubCrate.Add(itemToSell);
|
||||
}
|
||||
OnItemsInSellFromSubCrateChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void SellItems(List<PurchasedItem> itemsToSell, Store.StoreTab sellingMode)
|
||||
public void SellItems(Identifier storeIdentifier, List<PurchasedItem> itemsToSell, Store.StoreTab sellingMode)
|
||||
{
|
||||
IEnumerable<Item> sellableItems;
|
||||
try
|
||||
@@ -146,19 +139,24 @@ namespace Barotrauma
|
||||
}
|
||||
catch (NotImplementedException e)
|
||||
{
|
||||
DebugConsole.ShowError($"Error selling items: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}");
|
||||
DebugConsole.ShowError($"Error selling items: uknown store tab type \"{sellingMode}\".\n{e.StackTrace.CleanupStackTrace()}");
|
||||
return;
|
||||
}
|
||||
bool canAddToRemoveQueue = campaign.IsSinglePlayer && Entity.Spawner != null;
|
||||
byte sellerId = GameMain.Client?.ID ?? 0;
|
||||
// Check all the prices before starting the transaction
|
||||
// to make sure the modifiers stay the same for the whole transaction
|
||||
Dictionary<ItemPrefab, int> sellValues = GetSellValuesAtCurrentLocation(itemsToSell.Select(i => i.ItemPrefab));
|
||||
foreach (PurchasedItem item in itemsToSell)
|
||||
// Check all the prices before starting the transaction to make sure the modifiers stay the same for the whole transaction
|
||||
var sellValues = GetSellValuesAtCurrentLocation(storeIdentifier, itemsToSell.Select(i => i.ItemPrefab));
|
||||
if (!(Location.GetStore(storeIdentifier) is { } store))
|
||||
{
|
||||
DebugConsole.ShowError($"Error selling items at {Location}: no store with identifier \"{storeIdentifier}\" exists.\n{Environment.StackTrace.CleanupStackTrace()}");
|
||||
return;
|
||||
}
|
||||
var storeSpecificSoldItems = GetSoldItems(storeIdentifier, create: true);
|
||||
foreach (var item in itemsToSell)
|
||||
{
|
||||
int itemValue = item.Quantity * sellValues[item.ItemPrefab];
|
||||
// check if the store can afford the item
|
||||
if (Location.StoreCurrentBalance < itemValue) { continue; }
|
||||
if (store.Balance < itemValue) { continue; }
|
||||
// TODO: Write logic for prioritizing certain items over others (e.g. lone Battery Cell should be preferred over one inside a Stun Baton)
|
||||
var matchingItems = sellableItems.Where(i => i.Prefab == item.ItemPrefab);
|
||||
int count = Math.Min(item.Quantity, matchingItems.Count());
|
||||
@@ -168,9 +166,9 @@ namespace Barotrauma
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var matchingItem = matchingItems.ElementAt(i);
|
||||
SoldItems.Add(new SoldItem(matchingItem.Prefab, matchingItem.ID, canAddToRemoveQueue, sellerId, origin));
|
||||
storeSpecificSoldItems.Add(new SoldItem(matchingItem.Prefab, matchingItem.ID, canAddToRemoveQueue, sellerId, origin));
|
||||
SoldEntities.Add(new SoldEntity(matchingItem, campaign.IsSinglePlayer ? SoldEntity.SellStatus.Confirmed : SoldEntity.SellStatus.Local));
|
||||
if (canAddToRemoveQueue) { Entity.Spawner.AddToRemoveQueue(matchingItem); }
|
||||
if (canAddToRemoveQueue) { Entity.Spawner.AddItemToRemoveQueue(matchingItem); }
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -178,22 +176,23 @@ namespace Barotrauma
|
||||
// When selling from the sub in multiplayer, the server will determine the items that are sold
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
SoldItems.Add(new SoldItem(item.ItemPrefab, Entity.NullEntityID, canAddToRemoveQueue, sellerId, origin));
|
||||
storeSpecificSoldItems.Add(new SoldItem(item.ItemPrefab, Entity.NullEntityID, canAddToRemoveQueue, sellerId, origin));
|
||||
SoldEntities.Add(new SoldEntity(item.ItemPrefab, SoldEntity.SellStatus.Local));
|
||||
}
|
||||
}
|
||||
// Exchange money
|
||||
Location.StoreCurrentBalance -= itemValue;
|
||||
campaign.Money += itemValue;
|
||||
GameAnalyticsManager.AddMoneyGainedEvent(itemValue, GameAnalyticsManager.MoneySource.Store, item.ItemPrefab.Identifier);
|
||||
store.Balance -= itemValue;
|
||||
campaign.Bank.Give(itemValue);
|
||||
GameAnalyticsManager.AddMoneyGainedEvent(itemValue, GameAnalyticsManager.MoneySource.Store, item.ItemPrefab.Identifier.Value);
|
||||
|
||||
// Remove from the sell crate
|
||||
if ((sellingMode == Store.StoreTab.Sell ? ItemsInSellCrate : ItemsInSellFromSubCrate)?.Find(pi => pi.ItemPrefab == item.ItemPrefab) is { } itemToSell)
|
||||
var sellCrate = (sellingMode == Store.StoreTab.Sell ? GetSellCrateItems(storeIdentifier) : GetSubCrateItems(storeIdentifier));
|
||||
if (sellCrate?.Find(pi => pi.ItemPrefab == item.ItemPrefab) is { } itemToSell)
|
||||
{
|
||||
itemToSell.Quantity -= item.Quantity;
|
||||
if (itemToSell.Quantity < 1)
|
||||
{
|
||||
(sellingMode == Store.StoreTab.Sell ? ItemsInSellCrate : ItemsInSellFromSubCrate)?.Remove(itemToSell);
|
||||
sellCrate.Remove(itemToSell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
@@ -52,39 +53,39 @@ namespace Barotrauma
|
||||
|
||||
text = text.TrimEnd('\n');
|
||||
|
||||
List<RichTextData> richTextDatas = RichTextData.GetRichTextData(text, out text) ?? new List<RichTextData>();
|
||||
ImmutableArray<RichTextData>? richTextDatas = RichTextData.GetRichTextData(text, out text);
|
||||
|
||||
Vector2 size = GUI.SmallFont.MeasureString(text);
|
||||
Vector2 size = GUIStyle.SmallFont.MeasureString(text);
|
||||
Vector2 infoPos = new Vector2(GameMain.GraphicsWidth - size.X - 16, pos.Y + 8);
|
||||
Rectangle infoRect = new Rectangle(infoPos.ToPoint(), size.ToPoint());
|
||||
infoRect.Inflate(8, 8);
|
||||
GUI.DrawRectangle(spriteBatch, infoRect, Color.Black * 0.8f, isFilled: true);
|
||||
GUI.DrawRectangle(spriteBatch, infoRect, Color.White * 0.8f);
|
||||
|
||||
if (richTextDatas.Any())
|
||||
if (richTextDatas != null && richTextDatas.Value.Any())
|
||||
{
|
||||
GUI.DrawStringWithColors(spriteBatch, infoPos, text, Color.White, richTextDatas, font: GUI.SmallFont);
|
||||
GUI.DrawStringWithColors(spriteBatch, infoPos, text, Color.White, richTextDatas.Value, font: GUIStyle.SmallFont);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.DrawString(spriteBatch, infoPos, text, Color.White, font: GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, infoPos, text, Color.White, font: GUIStyle.SmallFont);
|
||||
}
|
||||
|
||||
float y = infoRect.Bottom + 16;
|
||||
if (Campaign.Factions != null)
|
||||
{
|
||||
const string factionHeader = "Reputations";
|
||||
Vector2 factionHeaderSize = GUI.SubHeadingFont.MeasureString(factionHeader);
|
||||
Vector2 factionHeaderSize = GUIStyle.SubHeadingFont.MeasureString(factionHeader);
|
||||
Vector2 factionPos = new Vector2(GameMain.GraphicsWidth - (264 / 2) - factionHeaderSize.X / 2, y);
|
||||
|
||||
GUI.DrawString(spriteBatch, factionPos, factionHeader, Color.White, font: GUI.SubHeadingFont);
|
||||
GUI.DrawString(spriteBatch, factionPos, factionHeader, Color.White, font: GUIStyle.SubHeadingFont);
|
||||
y += factionHeaderSize.Y + 8;
|
||||
|
||||
foreach (Faction faction in Campaign.Factions)
|
||||
{
|
||||
string name = faction.Prefab.Name;
|
||||
Vector2 nameSize = GUI.SmallFont.MeasureString(name);
|
||||
GUI.DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - 264, y), name, Color.White, font: GUI.SmallFont);
|
||||
LocalizedString name = faction.Prefab.Name;
|
||||
Vector2 nameSize = GUIStyle.SmallFont.MeasureString(name);
|
||||
GUI.DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - 264, y), name, Color.White, font: GUIStyle.SmallFont);
|
||||
y += nameSize.Y + 5;
|
||||
|
||||
Color color = ToolBox.GradientLerp(faction.Reputation.NormalizedValue, Color.Red, Color.Yellow, Color.LightGreen);
|
||||
@@ -98,8 +99,8 @@ namespace Barotrauma
|
||||
if (location?.Reputation != null)
|
||||
{
|
||||
string name = Campaign.Map?.CurrentLocation.Name;
|
||||
Vector2 nameSize = GUI.SmallFont.MeasureString(name);
|
||||
GUI.DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - 264, y), name, Color.White, font: GUI.SmallFont);
|
||||
Vector2 nameSize = GUIStyle.SmallFont.MeasureString(name);
|
||||
GUI.DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - 264, y), name, Color.White, font: GUIStyle.SmallFont);
|
||||
y += nameSize.Y + 5;
|
||||
|
||||
float normalizedReputation = MathUtils.InverseLerp(location.Reputation.MinReputation, location.Reputation.MaxReputation, location.Reputation.Value);
|
||||
@@ -107,8 +108,6 @@ namespace Barotrauma
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(GameMain.GraphicsWidth - 264, (int) y, (int)(normalizedReputation * 255), 10), color, isFilled: true);
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(GameMain.GraphicsWidth - 264, (int) y, 256, 10), Color.White);
|
||||
}
|
||||
|
||||
richTextDatas.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
namespace Barotrauma
|
||||
{
|
||||
internal partial class Wallet
|
||||
{
|
||||
public bool IsOwnWallet =>
|
||||
GameMain.GameSession?.Campaign switch
|
||||
{
|
||||
null => false,
|
||||
SinglePlayerCampaign spCampaign => this == spCampaign.Bank,
|
||||
MultiPlayerCampaign mpCampaign => this == mpCampaign.PersonalWallet,
|
||||
_ => false
|
||||
};
|
||||
|
||||
partial void SettingsChanged(Option<int> balanceChanged, Option<int> rewardChanged)
|
||||
{
|
||||
CampaignMode campaign = GameMain.GameSession?.Campaign;
|
||||
WalletChangedData data = new WalletChangedData
|
||||
{
|
||||
BalanceChanged = balanceChanged,
|
||||
RewardDistributionChanged = rewardChanged,
|
||||
};
|
||||
|
||||
campaign?.OnMoneyChanged.Invoke(new WalletChangedEvent(this, data, CreateWalletInfo()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ namespace Barotrauma
|
||||
protected bool crewDead;
|
||||
|
||||
protected Color overlayColor;
|
||||
protected string overlayText, overlayTextBottom;
|
||||
protected LocalizedString overlayText, overlayTextBottom;
|
||||
protected Color overlayTextColor;
|
||||
protected Sprite overlaySprite;
|
||||
|
||||
@@ -63,13 +63,19 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current personal wallet
|
||||
/// In singleplayer this is the campaign bank and in multiplayer this is the personal wallet
|
||||
/// </summary>
|
||||
public virtual Wallet Wallet => GetWallet();
|
||||
|
||||
public override void ShowStartMessage()
|
||||
{
|
||||
foreach (Mission mission in Missions.ToList())
|
||||
{
|
||||
new GUIMessageBox(
|
||||
mission.Prefab.IsSideObjective ? TextManager.AddPunctuation(':', TextManager.Get("sideobjective"), mission.Name) : mission.Name,
|
||||
mission.Description, new string[0], type: GUIMessageBox.Type.InGame, icon: mission.Prefab.Icon, parseRichText: true)
|
||||
RichString.Rich(mission.Prefab.IsSideObjective ? TextManager.AddPunctuation(':', TextManager.Get("sideobjective"), mission.Name) : mission.Name),
|
||||
RichString.Rich(mission.Description), Array.Empty<LocalizedString>(), type: GUIMessageBox.Type.InGame, icon: mission.Prefab.Icon)
|
||||
{
|
||||
IconColor = mission.Prefab.IconColor,
|
||||
UserData = "missionstartmessage"
|
||||
@@ -80,30 +86,14 @@ namespace Barotrauma
|
||||
/// <summary>
|
||||
/// There is a server-side implementation of the method in <see cref="MultiPlayerCampaign"/>
|
||||
/// </summary>
|
||||
public bool AllowedToEndRound()
|
||||
{
|
||||
//allow ending the round if the client has permissions, is the owner, the only client in the server
|
||||
//or if no-one has management permissions
|
||||
if (GameMain.Client == null) { return true; }
|
||||
return
|
||||
GameMain.Client.HasPermission(ClientPermissions.ManageRound) ||
|
||||
GameMain.Client.HasPermission(ClientPermissions.ManageCampaign) ||
|
||||
GameMain.Client.ConnectedClients.Count == 1 ||
|
||||
GameMain.Client.IsServerOwner ||
|
||||
GameMain.Client.ConnectedClients.None(c =>
|
||||
c.InGame && (c.IsOwner || c.HasPermission(ClientPermissions.ManageRound) || c.HasPermission(ClientPermissions.ManageCampaign)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// There is a server-side implementation of the method in <see cref="MultiPlayerCampaign"/>
|
||||
/// </summary>
|
||||
public bool AllowedToManageCampaign(ClientPermissions permissions = ClientPermissions.ManageCampaign)
|
||||
public bool AllowedToManageCampaign(ClientPermissions permissions)
|
||||
{
|
||||
//allow managing the round if the client has permissions, is the owner, the only client in the server,
|
||||
//or if no-one has management permissions
|
||||
if (GameMain.Client == null) { return true; }
|
||||
return
|
||||
GameMain.Client.HasPermission(permissions) ||
|
||||
GameMain.Client.HasPermission(ClientPermissions.ManageCampaign) ||
|
||||
GameMain.Client.ConnectedClients.Count == 1 ||
|
||||
GameMain.Client.IsServerOwner ||
|
||||
GameMain.Client.ConnectedClients.None(c => c.InGame && (c.IsOwner || c.HasPermission(permissions)));
|
||||
@@ -123,12 +113,12 @@ namespace Barotrauma
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), overlayColor, isFilled: true);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(overlayText) && overlayTextColor.A > 0)
|
||||
if (!overlayText.IsNullOrEmpty() && overlayTextColor.A > 0)
|
||||
{
|
||||
var backgroundSprite = GUI.Style.GetComponentStyle("CommandBackground").GetDefaultSprite();
|
||||
var backgroundSprite = GUIStyle.GetComponentStyle("CommandBackground").GetDefaultSprite();
|
||||
Vector2 centerPos = new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight) / 2;
|
||||
string wrappedText = ToolBox.WrapText(overlayText, GameMain.GraphicsWidth / 3, GUI.Font);
|
||||
Vector2 textSize = GUI.Font.MeasureString(wrappedText);
|
||||
LocalizedString wrappedText = ToolBox.WrapText(overlayText, GameMain.GraphicsWidth / 3, GUIStyle.Font);
|
||||
Vector2 textSize = GUIStyle.Font.MeasureString(wrappedText);
|
||||
Vector2 textPos = centerPos - textSize / 2;
|
||||
backgroundSprite.Draw(spriteBatch,
|
||||
centerPos,
|
||||
@@ -140,11 +130,11 @@ namespace Barotrauma
|
||||
GUI.DrawString(spriteBatch, textPos + Vector2.One, wrappedText, Color.Black * (overlayTextColor.A / 255.0f));
|
||||
GUI.DrawString(spriteBatch, textPos, wrappedText, overlayTextColor);
|
||||
|
||||
if (!string.IsNullOrEmpty(overlayTextBottom))
|
||||
if (!overlayTextBottom.IsNullOrEmpty())
|
||||
{
|
||||
Vector2 bottomTextPos = centerPos + new Vector2(0.0f, textSize.Y / 2 + 40 * GUI.Scale) - GUI.Font.MeasureString(overlayTextBottom) / 2;
|
||||
GUI.DrawString(spriteBatch, bottomTextPos + Vector2.One, overlayTextBottom, Color.Black * (overlayTextColor.A / 255.0f));
|
||||
GUI.DrawString(spriteBatch, bottomTextPos, overlayTextBottom, overlayTextColor);
|
||||
Vector2 bottomTextPos = centerPos + new Vector2(0.0f, textSize.Y / 2 + 40 * GUI.Scale) - GUIStyle.Font.MeasureString(overlayTextBottom) / 2;
|
||||
GUI.DrawString(spriteBatch, bottomTextPos + Vector2.One, overlayTextBottom.Value, Color.Black * (overlayTextColor.A / 255.0f));
|
||||
GUI.DrawString(spriteBatch, bottomTextPos, overlayTextBottom.Value, overlayTextColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -159,7 +149,7 @@ namespace Barotrauma
|
||||
|
||||
endRoundButton.Visible = false;
|
||||
var availableTransition = GetAvailableTransition(out _, out Submarine leavingSub);
|
||||
string buttonText = "";
|
||||
LocalizedString buttonText = "";
|
||||
switch (availableTransition)
|
||||
{
|
||||
case TransitionType.ProgressToNextLocation:
|
||||
@@ -188,7 +178,7 @@ namespace Barotrauma
|
||||
case TransitionType.None:
|
||||
default:
|
||||
if (Level.Loaded.Type == LevelData.LevelType.Outpost &&
|
||||
(Character.Controlled?.Submarine?.Info.Type == SubmarineType.Player || (Character.Controlled?.CurrentHull?.OutpostModuleTags.Contains("airlock") ?? false)))
|
||||
(Character.Controlled?.Submarine?.Info.Type == SubmarineType.Player || (Character.Controlled?.CurrentHull?.OutpostModuleTags.Contains("airlock".ToIdentifier()) ?? false)))
|
||||
{
|
||||
buttonText = TextManager.GetWithVariable("LeaveLocation", "[locationname]", Level.Loaded.StartLocation?.Name ?? "[ERROR]");
|
||||
endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI;
|
||||
@@ -204,7 +194,7 @@ namespace Barotrauma
|
||||
|
||||
if (endRoundButton.Visible)
|
||||
{
|
||||
if (!AllowedToEndRound())
|
||||
if (!AllowedToManageCampaign(ClientPermissions.ManageMap))
|
||||
{
|
||||
buttonText = TextManager.Get("map");
|
||||
}
|
||||
@@ -218,7 +208,7 @@ namespace Barotrauma
|
||||
endRoundButton.OnClicked(EndRoundButton, null);
|
||||
prevCampaignUIAutoOpenType = availableTransition;
|
||||
}
|
||||
endRoundButton.Text = ToolBox.LimitString(buttonText, endRoundButton.Font, endRoundButton.Rect.Width - 5);
|
||||
endRoundButton.Text = ToolBox.LimitString(buttonText.Value, endRoundButton.Font, endRoundButton.Rect.Width - 5);
|
||||
if (endRoundButton.Text != buttonText)
|
||||
{
|
||||
endRoundButton.ToolTip = buttonText;
|
||||
@@ -244,7 +234,7 @@ namespace Barotrauma
|
||||
if (ReadyCheck.ReadyCheckCooldown > DateTime.Now)
|
||||
{
|
||||
float progress = (ReadyCheck.ReadyCheckCooldown - DateTime.Now).Seconds / 60.0f;
|
||||
ReadyCheckButton.Color = ToolBox.GradientLerp(progress, Color.White, GUI.Style.Red);
|
||||
ReadyCheckButton.Color = ToolBox.GradientLerp(progress, Color.White, GUIStyle.Red);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -289,7 +279,7 @@ namespace Barotrauma
|
||||
case InteractionType.Examine:
|
||||
return;
|
||||
case InteractionType.Upgrade when !UpgradeManager.CanUpgradeSub():
|
||||
UpgradeManager.CreateUpgradeErrorMessage(TextManager.Get("Dialog.CantUpgrade"), IsSinglePlayer, npc);
|
||||
UpgradeManager.CreateUpgradeErrorMessage(TextManager.Get("Dialog.CantUpgrade").Value, IsSinglePlayer, npc);
|
||||
return;
|
||||
case InteractionType.Crew when GameMain.NetworkMember != null:
|
||||
CampaignUI.CrewManagement.SendCrewState(false);
|
||||
@@ -299,8 +289,8 @@ namespace Barotrauma
|
||||
goto default;
|
||||
default:
|
||||
ShowCampaignUI = true;
|
||||
CampaignUI.SelectTab(npc.CampaignInteractionType);
|
||||
CampaignUI.UpgradeStore?.RefreshAll();
|
||||
CampaignUI.SelectTab(npc.CampaignInteractionType, storeIdentifier: npc.MerchantIdentifier);
|
||||
CampaignUI.UpgradeStore?.RequestRefresh();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -310,7 +300,7 @@ namespace Barotrauma
|
||||
if (ShowCampaignUI || ForceMapUI)
|
||||
{
|
||||
campaignUIContainer?.AddToGUIUpdateList();
|
||||
if (CampaignUI?.UpgradeStore?.HoveredItem != null)
|
||||
if (CampaignUI?.UpgradeStore?.HoveredEntity != null)
|
||||
{
|
||||
if (CampaignUI.SelectedTab != InteractionType.Upgrade) { return; }
|
||||
CampaignUI?.UpgradeStore?.ItemInfoFrame.AddToGUIUpdateList(order: 1);
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Barotrauma
|
||||
private UInt16 pendingSaveID = 1;
|
||||
public UInt16 PendingSaveID
|
||||
{
|
||||
get
|
||||
get
|
||||
{
|
||||
return pendingSaveID;
|
||||
}
|
||||
@@ -34,7 +34,15 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public static void StartCampaignSetup(IEnumerable<string> saveFiles)
|
||||
public Wallet PersonalWallet => Character.Controlled?.Wallet ?? Wallet.Invalid;
|
||||
public override Wallet Wallet => GetWallet();
|
||||
|
||||
public override Wallet GetWallet(Client client = null)
|
||||
{
|
||||
return PersonalWallet;
|
||||
}
|
||||
|
||||
public static void StartCampaignSetup(List<SaveInfo> saveFiles)
|
||||
{
|
||||
var parent = GameMain.NetLobbyScreen.CampaignSetupFrame;
|
||||
parent.ClearChildren();
|
||||
@@ -195,6 +203,11 @@ namespace Barotrauma
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
if (GameMain.Client == null)
|
||||
{
|
||||
yield return CoroutineStatus.Failure;
|
||||
}
|
||||
|
||||
if (GameMain.Client.LateCampaignJoin)
|
||||
{
|
||||
GameMain.Client.LateCampaignJoin = false;
|
||||
@@ -217,8 +230,7 @@ namespace Barotrauma
|
||||
overlaySprite = Map.CurrentLocation.Type.GetPortrait(Map.CurrentLocation.PortraitId);
|
||||
overlayTextColor = Color.Transparent;
|
||||
overlayText = TextManager.GetWithVariables("campaignstart",
|
||||
new string[] { "xxxx", "yyyy" },
|
||||
new string[] { Map.CurrentLocation.Name, TextManager.Get("submarineclass." + Submarine.MainSub.Info.SubmarineClass) });
|
||||
("xxxx", Map.CurrentLocation.Name), ("yyyy", TextManager.Get($"submarineclass.{Submarine.MainSub.Info.SubmarineClass}")));
|
||||
float fadeInDuration = 1.0f;
|
||||
float textDuration = 10.0f;
|
||||
float timer = 0.0f;
|
||||
@@ -317,7 +329,7 @@ namespace Barotrauma
|
||||
|
||||
private IEnumerable<CoroutineStatus> DoLevelTransition()
|
||||
{
|
||||
SoundPlayer.OverrideMusicType = CrewManager.GetCharacters().Any(c => !c.IsDead) ? "endround" : "crewdead";
|
||||
SoundPlayer.OverrideMusicType = (CrewManager.GetCharacters().Any(c => !c.IsDead) ? "endround" : "crewdead").ToIdentifier();
|
||||
SoundPlayer.OverrideMusicDuration = 18.0f;
|
||||
|
||||
Level prevLevel = Level.Loaded;
|
||||
@@ -541,36 +553,10 @@ namespace Barotrauma
|
||||
msg.Write(PurchasedItemRepairs);
|
||||
msg.Write(PurchasedLostShuttles);
|
||||
|
||||
msg.Write((UInt16)CargoManager.ItemsInBuyCrate.Count);
|
||||
foreach (PurchasedItem pi in CargoManager.ItemsInBuyCrate)
|
||||
{
|
||||
msg.Write(pi.ItemPrefab.Identifier);
|
||||
msg.WriteRangedInteger(pi.Quantity, 0, CargoManager.MaxQuantity);
|
||||
}
|
||||
|
||||
msg.Write((UInt16)CargoManager.ItemsInSellFromSubCrate.Count);
|
||||
foreach (PurchasedItem pi in CargoManager.ItemsInSellFromSubCrate)
|
||||
{
|
||||
msg.Write(pi.ItemPrefab.Identifier);
|
||||
msg.WriteRangedInteger(pi.Quantity, 0, CargoManager.MaxQuantity);
|
||||
}
|
||||
|
||||
msg.Write((UInt16)CargoManager.PurchasedItems.Count);
|
||||
foreach (PurchasedItem pi in CargoManager.PurchasedItems)
|
||||
{
|
||||
msg.Write(pi.ItemPrefab.Identifier);
|
||||
msg.WriteRangedInteger(pi.Quantity, 0, CargoManager.MaxQuantity);
|
||||
}
|
||||
|
||||
msg.Write((UInt16)CargoManager.SoldItems.Count);
|
||||
foreach (SoldItem si in CargoManager.SoldItems)
|
||||
{
|
||||
msg.Write(si.ItemPrefab.Identifier);
|
||||
msg.Write((UInt16)si.ID);
|
||||
msg.Write(si.Removed);
|
||||
msg.Write(si.SellerID);
|
||||
msg.Write((byte)si.Origin);
|
||||
}
|
||||
WriteItems(msg, CargoManager.ItemsInBuyCrate);
|
||||
WriteItems(msg, CargoManager.ItemsInSellFromSubCrate);
|
||||
WriteItems(msg, CargoManager.PurchasedItems);
|
||||
WriteItems(msg, CargoManager.SoldItems);
|
||||
|
||||
msg.Write((ushort)UpgradeManager.PurchasedUpgrades.Count);
|
||||
foreach (var (prefab, category, level) in UpgradeManager.PurchasedUpgrades)
|
||||
@@ -584,7 +570,7 @@ namespace Barotrauma
|
||||
foreach (var itemSwap in UpgradeManager.PurchasedItemSwaps)
|
||||
{
|
||||
msg.Write(itemSwap.ItemToRemove.ID);
|
||||
msg.Write(itemSwap.ItemToInstall?.Identifier ?? string.Empty);
|
||||
msg.Write(itemSwap.ItemToInstall?.Identifier ?? Identifier.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -606,85 +592,63 @@ namespace Barotrauma
|
||||
selectedMissionIndices.Add(msg.ReadByte());
|
||||
}
|
||||
|
||||
ushort ownedSubCount = msg.ReadUInt16();
|
||||
List<ushort> ownedSubIndices = new List<ushort>();
|
||||
for (int i = 0; i < ownedSubCount; i++)
|
||||
{
|
||||
ownedSubIndices.Add(msg.ReadUInt16());
|
||||
}
|
||||
|
||||
bool allowDebugTeleport = msg.ReadBoolean();
|
||||
float? reputation = null;
|
||||
if (msg.ReadBoolean()) { reputation = msg.ReadSingle(); }
|
||||
|
||||
Dictionary<string, float> factionReps = new Dictionary<string, float>();
|
||||
Dictionary<Identifier, float> factionReps = new Dictionary<Identifier, float>();
|
||||
byte factionsCount = msg.ReadByte();
|
||||
for (int i = 0; i < factionsCount; i++)
|
||||
{
|
||||
factionReps.Add(msg.ReadString(), msg.ReadSingle());
|
||||
factionReps.Add(msg.ReadIdentifier(), msg.ReadSingle());
|
||||
}
|
||||
|
||||
bool forceMapUI = msg.ReadBoolean();
|
||||
|
||||
int money = msg.ReadInt32();
|
||||
bool purchasedHullRepairs = msg.ReadBoolean();
|
||||
bool purchasedItemRepairs = msg.ReadBoolean();
|
||||
bool purchasedLostShuttles = msg.ReadBoolean();
|
||||
|
||||
byte missionCount = msg.ReadByte();
|
||||
List<Pair<string, byte>> availableMissions = new List<Pair<string, byte>>();
|
||||
var availableMissions = new List<(Identifier Identifier, byte ConnectionIndex)>();
|
||||
for (int i = 0; i < missionCount; i++)
|
||||
{
|
||||
string missionIdentifier = msg.ReadString();
|
||||
Identifier missionIdentifier = msg.ReadIdentifier();
|
||||
byte connectionIndex = msg.ReadByte();
|
||||
availableMissions.Add(new Pair<string, byte>(missionIdentifier, connectionIndex));
|
||||
availableMissions.Add((missionIdentifier, connectionIndex));
|
||||
}
|
||||
|
||||
UInt16? storeBalance = null;
|
||||
var storeBalances = new Dictionary<Identifier, UInt16>();
|
||||
if (msg.ReadBoolean())
|
||||
{
|
||||
storeBalance = msg.ReadUInt16();
|
||||
byte storeCount = msg.ReadByte();
|
||||
for (int i = 0; i < storeCount; i++)
|
||||
{
|
||||
Identifier identifier = msg.ReadIdentifier();
|
||||
UInt16 storeBalance = msg.ReadUInt16();
|
||||
storeBalances.Add(identifier, storeBalance);
|
||||
}
|
||||
}
|
||||
|
||||
UInt16 buyCrateItemCount = msg.ReadUInt16();
|
||||
List<PurchasedItem> buyCrateItems = new List<PurchasedItem>();
|
||||
for (int i = 0; i < buyCrateItemCount; i++)
|
||||
{
|
||||
string itemPrefabIdentifier = msg.ReadString();
|
||||
int itemQuantity = msg.ReadRangedInteger(0, CargoManager.MaxQuantity);
|
||||
buyCrateItems.Add(new PurchasedItem(ItemPrefab.Prefabs[itemPrefabIdentifier], itemQuantity));
|
||||
}
|
||||
|
||||
UInt16 subSellCrateItemCount = msg.ReadUInt16();
|
||||
List<PurchasedItem> subSellCrateItems = new List<PurchasedItem>();
|
||||
for (int i = 0; i < subSellCrateItemCount; i++)
|
||||
{
|
||||
string itemPrefabIdentifier = msg.ReadString();
|
||||
int itemQuantity = msg.ReadRangedInteger(0, CargoManager.MaxQuantity);
|
||||
subSellCrateItems.Add(new PurchasedItem(ItemPrefab.Prefabs[itemPrefabIdentifier], itemQuantity));
|
||||
}
|
||||
|
||||
UInt16 purchasedItemCount = msg.ReadUInt16();
|
||||
List<PurchasedItem> purchasedItems = new List<PurchasedItem>();
|
||||
for (int i = 0; i < purchasedItemCount; i++)
|
||||
{
|
||||
string itemPrefabIdentifier = msg.ReadString();
|
||||
int itemQuantity = msg.ReadRangedInteger(0, CargoManager.MaxQuantity);
|
||||
purchasedItems.Add(new PurchasedItem(ItemPrefab.Prefabs[itemPrefabIdentifier], itemQuantity));
|
||||
}
|
||||
|
||||
UInt16 soldItemCount = msg.ReadUInt16();
|
||||
List<SoldItem> soldItems = new List<SoldItem>();
|
||||
for (int i = 0; i < soldItemCount; i++)
|
||||
{
|
||||
string itemPrefabIdentifier = msg.ReadString();
|
||||
UInt16 id = msg.ReadUInt16();
|
||||
bool removed = msg.ReadBoolean();
|
||||
byte sellerId = msg.ReadByte();
|
||||
byte origin = msg.ReadByte();
|
||||
soldItems.Add(new SoldItem(ItemPrefab.Prefabs[itemPrefabIdentifier], id, removed, sellerId, (SoldItem.SellOrigin)origin));
|
||||
}
|
||||
var buyCrateItems = ReadPurchasedItems(msg, sender: null);
|
||||
var subSellCrateItems = ReadPurchasedItems(msg, sender: null);
|
||||
var purchasedItems = ReadPurchasedItems(msg, sender: null);
|
||||
var soldItems = ReadSoldItems(msg);
|
||||
|
||||
ushort pendingUpgradeCount = msg.ReadUInt16();
|
||||
List<PurchasedUpgrade> pendingUpgrades = new List<PurchasedUpgrade>();
|
||||
for (int i = 0; i < pendingUpgradeCount; i++)
|
||||
{
|
||||
string upgradeIdentifier = msg.ReadString();
|
||||
Identifier upgradeIdentifier = msg.ReadIdentifier();
|
||||
UpgradePrefab prefab = UpgradePrefab.Find(upgradeIdentifier);
|
||||
string categoryIdentifier = msg.ReadString();
|
||||
Identifier categoryIdentifier = msg.ReadIdentifier();
|
||||
UpgradeCategory category = UpgradeCategory.Find(categoryIdentifier);
|
||||
int upgradeLevel = msg.ReadByte();
|
||||
if (prefab == null || category == null) { continue; }
|
||||
@@ -696,8 +660,8 @@ namespace Barotrauma
|
||||
for (int i = 0; i < purchasedItemSwapCount; i++)
|
||||
{
|
||||
UInt16 itemToRemoveID = msg.ReadUInt16();
|
||||
string itemToInstallIdentifier = msg.ReadString();
|
||||
ItemPrefab itemToInstall = string.IsNullOrEmpty(itemToInstallIdentifier) ? null : ItemPrefab.Find(string.Empty, itemToInstallIdentifier);
|
||||
Identifier itemToInstallIdentifier = msg.ReadIdentifier();
|
||||
ItemPrefab itemToInstall = itemToInstallIdentifier.IsEmpty ? null : ItemPrefab.Find(string.Empty, itemToInstallIdentifier);
|
||||
if (!(Entity.FindEntityByID(itemToRemoveID) is Item itemToRemove)) { continue; }
|
||||
purchasedItemSwaps.Add(new PurchasedItemSwap(itemToRemove, itemToInstall));
|
||||
}
|
||||
@@ -740,12 +704,29 @@ namespace Barotrauma
|
||||
campaign.Map.SetLocation(currentLocIndex == UInt16.MaxValue ? -1 : currentLocIndex);
|
||||
campaign.Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex);
|
||||
campaign.Map.SelectMission(selectedMissionIndices);
|
||||
|
||||
GameMain.GameSession.OwnedSubmarines.Clear();
|
||||
foreach (int ownedSubIndex in ownedSubIndices)
|
||||
{
|
||||
SubmarineInfo sub = GameMain.Client.ServerSubmarines[ownedSubIndex];
|
||||
if (GameMain.NetLobbyScreen.CheckIfCampaignSubMatches(sub, NetLobbyScreen.SubmarineDeliveryData.Owned))
|
||||
{
|
||||
GameMain.GameSession.OwnedSubmarines.Add(sub);
|
||||
}
|
||||
}
|
||||
|
||||
campaign.Map.AllowDebugTeleport = allowDebugTeleport;
|
||||
campaign.CargoManager.SetItemsInBuyCrate(buyCrateItems);
|
||||
campaign.CargoManager.SetItemsInSubSellCrate(subSellCrateItems);
|
||||
campaign.CargoManager.SetPurchasedItems(purchasedItems);
|
||||
campaign.CargoManager.SetSoldItems(soldItems);
|
||||
if (storeBalance.HasValue) { campaign.Map.CurrentLocation.StoreCurrentBalance = storeBalance.Value; }
|
||||
foreach (var balance in storeBalances)
|
||||
{
|
||||
if (campaign.Map.CurrentLocation.GetStore(balance.Key) is { } store)
|
||||
{
|
||||
store.Balance = balance.Value;
|
||||
}
|
||||
}
|
||||
campaign.UpgradeManager.SetPendingUpgrades(pendingUpgrades);
|
||||
campaign.UpgradeManager.PurchasedUpgrades.Clear();
|
||||
foreach (var purchasedItemSwap in purchasedItemSwaps)
|
||||
@@ -769,7 +750,7 @@ namespace Barotrauma
|
||||
|
||||
foreach (var (identifier, rep) in factionReps)
|
||||
{
|
||||
Faction faction = campaign.Factions.FirstOrDefault(f => f.Prefab.Identifier.Equals(identifier, StringComparison.OrdinalIgnoreCase));
|
||||
Faction faction = campaign.Factions.FirstOrDefault(f => f.Prefab.Identifier == identifier);
|
||||
if (faction?.Reputation != null)
|
||||
{
|
||||
faction.Reputation.SetReputation(rep);
|
||||
@@ -783,29 +764,29 @@ namespace Barotrauma
|
||||
if (reputation.HasValue)
|
||||
{
|
||||
campaign.Map.CurrentLocation.Reputation.SetReputation(reputation.Value);
|
||||
campaign?.CampaignUI?.UpgradeStore?.RefreshAll();
|
||||
campaign?.CampaignUI?.UpgradeStore?.RequestRefresh();
|
||||
}
|
||||
|
||||
foreach (var availableMission in availableMissions)
|
||||
{
|
||||
MissionPrefab missionPrefab = MissionPrefab.List.Find(mp => mp.Identifier == availableMission.First);
|
||||
MissionPrefab missionPrefab = MissionPrefab.Prefabs.Find(mp => mp.Identifier == availableMission.Identifier);
|
||||
if (missionPrefab == null)
|
||||
{
|
||||
DebugConsole.ThrowError($"Error when receiving campaign data from the server: mission prefab \"{availableMission.First}\" not found.");
|
||||
DebugConsole.ThrowError($"Error when receiving campaign data from the server: mission prefab \"{availableMission.Identifier}\" not found.");
|
||||
continue;
|
||||
}
|
||||
if (availableMission.Second == 255)
|
||||
if (availableMission.ConnectionIndex == 255)
|
||||
{
|
||||
campaign.Map.CurrentLocation.UnlockMission(missionPrefab);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (availableMission.Second < 0 || availableMission.Second >= campaign.Map.CurrentLocation.Connections.Count)
|
||||
if (availableMission.ConnectionIndex < 0 || availableMission.ConnectionIndex >= campaign.Map.CurrentLocation.Connections.Count)
|
||||
{
|
||||
DebugConsole.ThrowError($"Error when receiving campaign data from the server: connection index for mission \"{availableMission.First}\" out of range (index: {availableMission.Second}, current location: {campaign.Map.CurrentLocation.Name}, connections: {campaign.Map.CurrentLocation.Connections.Count}).");
|
||||
DebugConsole.ThrowError($"Error when receiving campaign data from the server: connection index for mission \"{availableMission.Identifier}\" out of range (index: {availableMission.ConnectionIndex}, current location: {campaign.Map.CurrentLocation.Name}, connections: {campaign.Map.CurrentLocation.Connections.Count}).");
|
||||
continue;
|
||||
}
|
||||
LocationConnection connection = campaign.Map.CurrentLocation.Connections[availableMission.Second];
|
||||
LocationConnection connection = campaign.Map.CurrentLocation.Connections[availableMission.ConnectionIndex];
|
||||
campaign.Map.CurrentLocation.UnlockMission(missionPrefab, connection);
|
||||
}
|
||||
}
|
||||
@@ -813,19 +794,17 @@ namespace Barotrauma
|
||||
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
|
||||
}
|
||||
|
||||
bool shouldRefresh = campaign.Money != money ||
|
||||
campaign.PurchasedHullRepairs != purchasedHullRepairs ||
|
||||
bool shouldRefresh = campaign.PurchasedHullRepairs != purchasedHullRepairs ||
|
||||
campaign.PurchasedItemRepairs != purchasedItemRepairs ||
|
||||
campaign.PurchasedLostShuttles != purchasedLostShuttles;
|
||||
|
||||
campaign.Money = money;
|
||||
campaign.PurchasedHullRepairs = purchasedHullRepairs;
|
||||
campaign.PurchasedItemRepairs = purchasedItemRepairs;
|
||||
campaign.PurchasedLostShuttles = purchasedLostShuttles;
|
||||
|
||||
if (shouldRefresh)
|
||||
{
|
||||
campaign?.CampaignUI?.UpgradeStore?.RefreshAll();
|
||||
campaign?.CampaignUI?.UpgradeStore?.RequestRefresh();
|
||||
}
|
||||
|
||||
if (myCharacterInfo != null)
|
||||
@@ -849,7 +828,7 @@ namespace Barotrauma
|
||||
List<CharacterInfo> availableHires = new List<CharacterInfo>();
|
||||
for (int i = 0; i < availableHireLength; i++)
|
||||
{
|
||||
CharacterInfo hire = CharacterInfo.ClientRead("human", msg);
|
||||
CharacterInfo hire = CharacterInfo.ClientRead(CharacterPrefab.HumanSpeciesName, msg);
|
||||
hire.Salary = msg.ReadInt32();
|
||||
availableHires.Add(hire);
|
||||
}
|
||||
@@ -865,7 +844,7 @@ namespace Barotrauma
|
||||
List<CharacterInfo> hiredCharacters = new List<CharacterInfo>();
|
||||
for (int i = 0; i < hiredLength; i++)
|
||||
{
|
||||
CharacterInfo hired = CharacterInfo.ClientRead("human", msg);
|
||||
CharacterInfo hired = CharacterInfo.ClientRead(CharacterPrefab.HumanSpeciesName, msg);
|
||||
hired.Salary = msg.ReadInt32();
|
||||
hiredCharacters.Add(hired);
|
||||
}
|
||||
@@ -897,6 +876,43 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientReadMoney(IReadMessage inc)
|
||||
{
|
||||
NetWalletUpdate update = INetSerializableStruct.Read<NetWalletUpdate>(inc);
|
||||
foreach (NetWalletTransaction transaction in update.Transactions)
|
||||
{
|
||||
WalletInfo info = transaction.Info;
|
||||
switch (transaction.CharacterID)
|
||||
{
|
||||
case Some<ushort> { Value: var charID }:
|
||||
{
|
||||
Character targetCharacter = Character.CharacterList?.FirstOrDefault(c => c.ID == charID);
|
||||
if (targetCharacter is null) { break; }
|
||||
Wallet wallet = targetCharacter.Wallet;
|
||||
|
||||
wallet.Balance = info.Balance;
|
||||
wallet.RewardDistribution = info.RewardDistribution;
|
||||
TryInvokeEvent(wallet, transaction.ChangedData, info);
|
||||
break;
|
||||
}
|
||||
case None<ushort> _:
|
||||
{
|
||||
Bank.Balance = info.Balance;
|
||||
TryInvokeEvent(Bank, transaction.ChangedData, info);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TryInvokeEvent(Wallet wallet, WalletChangedData data, WalletInfo info)
|
||||
{
|
||||
if (data.BalanceChanged.IsSome() || data.RewardDistributionChanged.IsSome())
|
||||
{
|
||||
OnMoneyChanged.Invoke(new WalletChangedEvent(wallet, data, info));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Save(XElement element)
|
||||
{
|
||||
//do nothing, the clients get the save files from the server
|
||||
@@ -909,10 +925,10 @@ namespace Barotrauma
|
||||
|
||||
string gamesessionDocPath = Path.Combine(SaveUtil.TempPath, "gamesession.xml");
|
||||
XDocument doc = XMLExtensions.TryLoadXml(gamesessionDocPath);
|
||||
if (doc == null)
|
||||
if (doc == null)
|
||||
{
|
||||
DebugConsole.ThrowError($"Failed to load the state of a multiplayer campaign. Could not open the file \"{gamesessionDocPath}\".");
|
||||
return;
|
||||
return;
|
||||
}
|
||||
Load(doc.Root.Element("MultiPlayerCampaign"));
|
||||
GameMain.GameSession.OwnedSubmarines = SaveUtil.LoadOwnedSubmarines(doc, out SubmarineInfo selectedSub);
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Networking;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -68,7 +69,7 @@ namespace Barotrauma
|
||||
for (int i = 0; i < jobPrefab.InitialCount; i++)
|
||||
{
|
||||
var variant = Rand.Range(0, jobPrefab.Variants);
|
||||
CrewManager.AddCharacterInfo(new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: jobPrefab, variant: variant));
|
||||
CrewManager.AddCharacterInfo(new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: jobPrefab, variant: variant));
|
||||
}
|
||||
}
|
||||
InitCampaignData();
|
||||
@@ -82,7 +83,7 @@ namespace Barotrauma
|
||||
{
|
||||
IsFirstRound = false;
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
@@ -108,6 +109,9 @@ namespace Barotrauma
|
||||
case "pets":
|
||||
petsElement = subElement;
|
||||
break;
|
||||
case Wallet.LowerCaseSaveElementName:
|
||||
Bank = new Wallet(Option<Character>.None(), subElement);
|
||||
break;
|
||||
case "stats":
|
||||
LoadStats(subElement);
|
||||
break;
|
||||
@@ -121,7 +125,16 @@ namespace Barotrauma
|
||||
|
||||
InitUI();
|
||||
|
||||
Money = element.GetAttributeInt("money", 0);
|
||||
//backwards compatibility for saves made prior to the addition of personal wallets
|
||||
int oldMoney = element.GetAttributeInt("money", 0);
|
||||
if (oldMoney > 0)
|
||||
{
|
||||
Bank = new Wallet(Option<Character>.None())
|
||||
{
|
||||
Balance = oldMoney
|
||||
};
|
||||
}
|
||||
|
||||
PurchasedLostShuttles = element.GetAttributeBool("purchasedlostshuttles", false);
|
||||
PurchasedHullRepairs = element.GetAttributeBool("purchasedhullrepairs", false);
|
||||
PurchasedItemRepairs = element.GetAttributeBool("purchaseditemrepairs", false);
|
||||
@@ -283,9 +296,9 @@ namespace Barotrauma
|
||||
overlaySprite = Map.CurrentLocation.Type.GetPortrait(Map.CurrentLocation.PortraitId);
|
||||
overlayTextColor = Color.Transparent;
|
||||
overlayText = TextManager.GetWithVariables(showCampaignResetText ? "campaignend4" : "campaignstart",
|
||||
new string[] { "xxxx", "yyyy" },
|
||||
new string[] { Map.CurrentLocation.Name, TextManager.Get("submarineclass." + Submarine.MainSub.Info.SubmarineClass) });
|
||||
string pressAnyKeyText = TextManager.Get("pressanykey");
|
||||
("xxxx", Map.CurrentLocation.Name),
|
||||
("yyyy", TextManager.Get("submarineclass." + Submarine.MainSub.Info.SubmarineClass)));
|
||||
LocalizedString pressAnyKeyText = TextManager.Get("pressanykey");
|
||||
float fadeInDuration = 2.0f;
|
||||
float textDuration = 10.0f;
|
||||
float timer = 0.0f;
|
||||
@@ -385,7 +398,7 @@ namespace Barotrauma
|
||||
{
|
||||
NextLevel = newLevel;
|
||||
bool success = CrewManager.GetCharacters().Any(c => !c.IsDead);
|
||||
SoundPlayer.OverrideMusicType = success ? "endround" : "crewdead";
|
||||
SoundPlayer.OverrideMusicType = (success ? "endround" : "crewdead").ToIdentifier();
|
||||
SoundPlayer.OverrideMusicDuration = 18.0f;
|
||||
GUI.SetSavingIndicatorState(success);
|
||||
crewDead = false;
|
||||
@@ -672,9 +685,9 @@ namespace Barotrauma
|
||||
var subsToLeaveBehind = GetSubsToLeaveBehind(leavingSub);
|
||||
if (subsToLeaveBehind.Any())
|
||||
{
|
||||
string msg = TextManager.Get(subsToLeaveBehind.Count == 1 ? "LeaveSubBehind" : "LeaveSubsBehind");
|
||||
LocalizedString msg = TextManager.Get(subsToLeaveBehind.Count == 1 ? "LeaveSubBehind" : "LeaveSubsBehind");
|
||||
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("Warning"), msg, new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("Warning"), msg, new LocalizedString[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||
msgBox.Buttons[0].OnClicked += (btn, userdata) => { LoadNewLevel(); return true; } ;
|
||||
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
||||
msgBox.Buttons[0].UserData = Submarine.Loaded.FindAll(s => !subsToLeaveBehind.Contains(s));
|
||||
@@ -729,7 +742,6 @@ namespace Barotrauma
|
||||
public override void Save(XElement element)
|
||||
{
|
||||
XElement modeElement = new XElement("SinglePlayerCampaign",
|
||||
new XAttribute("money", Money),
|
||||
new XAttribute("purchasedlostshuttles", PurchasedLostShuttles),
|
||||
new XAttribute("purchasedhullrepairs", PurchasedHullRepairs),
|
||||
new XAttribute("purchaseditemrepairs", PurchasedItemRepairs),
|
||||
@@ -756,13 +768,14 @@ namespace Barotrauma
|
||||
|
||||
petsElement = new XElement("pets");
|
||||
PetBehavior.SavePets(petsElement);
|
||||
modeElement.Add(petsElement);
|
||||
modeElement.Add(petsElement);
|
||||
|
||||
CrewManager.Save(modeElement);
|
||||
CampaignMetadata.Save(modeElement);
|
||||
Map.Save(modeElement);
|
||||
CargoManager?.SavePurchasedItems(modeElement);
|
||||
UpgradeManager?.Save(modeElement);
|
||||
modeElement.Add(Bank.Save());
|
||||
element.Add(modeElement);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,12 +24,12 @@ namespace Barotrauma
|
||||
|
||||
public TestGameMode(GameModePreset preset) : base(preset)
|
||||
{
|
||||
foreach (JobPrefab jobPrefab in JobPrefab.Prefabs)
|
||||
foreach (JobPrefab jobPrefab in JobPrefab.Prefabs.OrderBy(p => p.Identifier))
|
||||
{
|
||||
for (int i = 0; i < jobPrefab.InitialCount; i++)
|
||||
{
|
||||
var variant = Rand.Range(0, jobPrefab.Variants);
|
||||
CrewManager.AddCharacterInfo(new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: jobPrefab, variant: variant));
|
||||
CrewManager.AddCharacterInfo(new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: jobPrefab, variant: variant));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -93,7 +93,7 @@ namespace Barotrauma
|
||||
|
||||
private void GenerateOutpost(Submarine submarine)
|
||||
{
|
||||
Submarine outpost = OutpostGenerator.Generate(OutpostParams ?? OutpostGenerationParams.Params.GetRandom(), OutpostType ?? LocationType.List.GetRandom());
|
||||
Submarine outpost = OutpostGenerator.Generate(OutpostParams ?? OutpostGenerationParams.OutpostParams.GetRandomUnsynced(), OutpostType ?? LocationType.Prefabs.GetRandomUnsynced());
|
||||
outpost.SetPosition(Vector2.Zero);
|
||||
|
||||
float closestDistance = 0.0f;
|
||||
@@ -131,7 +131,7 @@ namespace Barotrauma
|
||||
|
||||
if (Character.Controlled != null)
|
||||
{
|
||||
Character.Controlled.TeleportTo(outpost.GetWaypoints(false).GetRandom(point => point.SpawnType == SpawnType.Human).WorldPosition);
|
||||
Character.Controlled.TeleportTo(outpost.GetWaypoints(false).GetRandomUnsynced(point => point.SpawnType == SpawnType.Human).WorldPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,683 +0,0 @@
|
||||
using Barotrauma.Items.Components;
|
||||
using FarseerPhysics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Tutorials
|
||||
{
|
||||
class BasicTutorial : ScenarioTutorial
|
||||
{
|
||||
public BasicTutorial(XElement element)
|
||||
: base(element)
|
||||
{
|
||||
}
|
||||
|
||||
public override IEnumerable<CoroutineStatus> UpdateState()
|
||||
{
|
||||
Character Controlled = Character.Controlled;
|
||||
if (Controlled == null) yield return CoroutineStatus.Success;
|
||||
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
var wire = item.GetComponent<Wire>();
|
||||
if (wire != null && wire.Connections.Any(c => c != null))
|
||||
{
|
||||
wire.Locked = true;
|
||||
}
|
||||
}
|
||||
|
||||
//remove all characters except the controlled one to prevent any unintended monster attacks
|
||||
var existingCharacters = Character.CharacterList.FindAll(c => c != Controlled);
|
||||
foreach (Character c in existingCharacters)
|
||||
{
|
||||
c.Remove();
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(4.0f);
|
||||
|
||||
infoBox = CreateInfoFrame("", "Use WASD to move and the mouse to look around");
|
||||
|
||||
yield return new WaitForSeconds(5.0f);
|
||||
|
||||
//-----------------------------------
|
||||
|
||||
infoBox = CreateInfoFrame("", "Open the door at your right side by highlighting the button next to it with your cursor and pressing E");
|
||||
|
||||
Door tutorialDoor = Item.ItemList.Find(i => i.HasTag("tutorialdoor")).GetComponent<Door>();
|
||||
|
||||
while (!tutorialDoor.IsOpen && Controlled.WorldPosition.X < tutorialDoor.Item.WorldPosition.X)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(2.0f);
|
||||
|
||||
//-----------------------------------
|
||||
|
||||
infoBox = CreateInfoFrame("", "Hold W or S to walk up or down stairs. Use shift to run.", hasButton: true);
|
||||
|
||||
while (infoBox != null)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
//-----------------------------------
|
||||
|
||||
infoBox = CreateInfoFrame("", "At the moment the submarine has no power, which means that crucial systems such as the oxygen generator or the engine aren't running. Let's fix this: go to the upper left corner of the submarine, where you'll find a nuclear reactor.");
|
||||
|
||||
Reactor reactor = Item.ItemList.Find(i => i.HasTag("tutorialreactor")).GetComponent<Reactor>();
|
||||
//reactor.MeltDownTemp = 20000.0f;
|
||||
|
||||
while (Vector2.Distance(Controlled.Position, reactor.Item.Position) > 200.0f)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "The reactor requires fuel rods to generate power. You can grab one from the steel cabinet by walking next to it and pressing E.");
|
||||
|
||||
while (Controlled.SelectedConstruction == null || Controlled.SelectedConstruction.Prefab.Identifier != "steelcabinet")
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "Pick up one of the fuel rods either by double-clicking or dragging and dropping it into your inventory.");
|
||||
|
||||
while (!HasItem("fuelrod"))
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "Select the reactor by walking next to it and pressing E.");
|
||||
|
||||
while (Controlled.SelectedConstruction != reactor.Item)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
infoBox = CreateInfoFrame("", "Load the fuel rod into the reactor by dropping it into any of the 5 slots.");
|
||||
|
||||
while (reactor.AvailableFuel <= 0.0f)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "The reactor is now fueled up. Try turning it on by increasing the fission rate.");
|
||||
|
||||
while (reactor.FissionRate <= 0.0f)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
infoBox = CreateInfoFrame("", "The reactor core has started generating heat, which in turn generates power for the submarine. The power generation is very low at the moment,"
|
||||
+ " because the reactor is set to shut itself down when the temperature rises above 500 degrees Celsius. You can adjust the temperature limit by changing the \"Shutdown Temperature\" in the control panel.", hasButton: true);
|
||||
|
||||
//TODO: reimplement
|
||||
/*while (infoBox != null)
|
||||
{
|
||||
reactor.ShutDownTemp = Math.Min(reactor.ShutDownTemp, 5000.0f);
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
infoBox = CreateInfoFrame("The amount of power generated by the reactor should be kept close to the amount of power consumed by the devices in the submarine. "
|
||||
+ "If there isn't enough power, devices won't function properly (or at all), and if there's too much power, some devices may be damaged."
|
||||
+ " Try to raise the temperature of the reactor close to 3000 degrees by adjusting the fission and cooling rates.", true);
|
||||
|
||||
while (Math.Abs(reactor.Temperature - 3000.0f) > 100.0f)
|
||||
{
|
||||
reactor.AutoTemp = false;
|
||||
reactor.ShutDownTemp = Math.Min(reactor.ShutDownTemp, 5000.0f);
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
infoBox = CreateInfoFrame("Looks like we're up and running! Now you should turn on the \"Automatic temperature control\", which will make the reactor "
|
||||
+ "automatically adjust the temperature to a suitable level. Even though it's an easy way to keep the reactor up and running most of the time, "
|
||||
+ "you should keep in mind that it changes the temperature very slowly and carefully, which may cause issues if there are sudden changes in grid load.");
|
||||
|
||||
while (!reactor.AutoTemp)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}*/
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
infoBox = CreateInfoFrame("", "That's the basics of operating the reactor! Now that there's power available for the engines, it's time to get the submarine moving. "
|
||||
+ "Deselect the reactor by pressing E and head to the command room at the right edge of the vessel.");
|
||||
|
||||
Steering steering = Item.ItemList.Find(i => i.HasTag("tutorialsteering")).GetComponent<Steering>();
|
||||
Sonar sonar = steering.Item.GetComponent<Sonar>();
|
||||
|
||||
while (Vector2.Distance(Controlled.Position, steering.Item.Position) > 150.0f)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
CoroutineManager.StartCoroutine(KeepReactorRunning(reactor));
|
||||
|
||||
infoBox = CreateInfoFrame("", "Select the navigation terminal by walking next to it and pressing E.");
|
||||
|
||||
while (Controlled.SelectedConstruction != steering.Item)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
infoBox = CreateInfoFrame("", "There seems to be something wrong with the navigation terminal." +
|
||||
" There's nothing on the monitor, so it's probably out of power. The reactor must still be"
|
||||
+ " running or the lights would've gone out, so it's most likely a problem with the wiring."
|
||||
+ " Deselect the terminal by pressing E to start checking the wiring.");
|
||||
|
||||
while (Controlled.SelectedConstruction == steering.Item)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
|
||||
infoBox = CreateInfoFrame("", "You need a screwdriver to check the wiring of the terminal."
|
||||
+ " Equip a screwdriver by pulling it to either of the slots with a hand symbol, and then use it on the terminal by left clicking.");
|
||||
|
||||
while (Controlled.SelectedConstruction != steering.Item ||
|
||||
Controlled.HeldItems.FirstOrDefault(i => i.Prefab.Identifier == "screwdriver") == null)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
|
||||
infoBox = CreateInfoFrame("", "Here you can see all the wires connected to the terminal. Apparently there's no wire"
|
||||
+ " going into the to the power connection - that's why the monitor isn't working."
|
||||
+ " You should find a piece of wire to connect it. Try searching some of the cabinets scattered around the sub.");
|
||||
|
||||
while (!HasItem("wire"))
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "Head back to the navigation terminal to fix the wiring.");
|
||||
|
||||
PowerTransfer junctionBox = Item.ItemList.Find(i => i != null && i.HasTag("tutorialjunctionbox")).GetComponent<PowerTransfer>();
|
||||
|
||||
while ((Controlled.SelectedConstruction != junctionBox.Item &&
|
||||
Controlled.SelectedConstruction != steering.Item) ||
|
||||
!Controlled.HeldItems.Any(i => i.Prefab.Identifier == "screwdriver"))
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
if (!Controlled.HeldItems.Any(i => i.GetComponent<Wire>() != null))
|
||||
{
|
||||
infoBox = CreateInfoFrame("", "Equip the wire by dragging it to one of the slots with a hand symbol.");
|
||||
|
||||
while (!Controlled.HeldItems.Any(i => i.GetComponent<Wire>() != null))
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "You can see the equipped wire at the middle of the connection panel. Drag it to the power connector.");
|
||||
|
||||
var steeringConnection = steering.Item.Connections.Find(c => c.Name.Contains("power"));
|
||||
|
||||
while (steeringConnection.Wires.FirstOrDefault(w => w != null) == null)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "Now you have to connect the other end of the wire to a power source. "
|
||||
+ "The junction box in the room just below the command room should do.");
|
||||
|
||||
while (Controlled.SelectedConstruction != null)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(2.0f);
|
||||
|
||||
infoBox = CreateInfoFrame("", "You can now move the other end of the wire around, and attach it on the wall by left clicking or "
|
||||
+ "remove the previous attachment by right clicking. Or if you don't care for neatly laid out wiring, you can just "
|
||||
+ "run it straight to the junction box.");
|
||||
|
||||
while (Controlled.SelectedConstruction == null || Controlled.SelectedConstruction.GetComponent<PowerTransfer>() == null)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "Connect the wire to the junction box by pulling it to the power connection, the same way you did with the navigation terminal.");
|
||||
|
||||
while (sonar.Voltage < 0.1f)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "Great! Now we should be able to get moving.");
|
||||
|
||||
|
||||
while (Controlled.SelectedConstruction != steering.Item)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "You can take a look at the area around the sub by selecting the \"Active Sonar\" checkbox.");
|
||||
|
||||
while (!sonar.IsActive)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
infoBox = CreateInfoFrame("", "The blue rectangle in the middle is the submarine, and the flickering shapes outside it are the walls of an underwater cavern. "
|
||||
+ "Try moving the submarine by clicking somewhere on the monitor and dragging the pointer to the direction you want to go to.");
|
||||
|
||||
while (steering.TargetVelocity == Vector2.Zero && steering.TargetVelocity.Length() < 50.0f)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
yield return new WaitForSeconds(4.0f);
|
||||
|
||||
infoBox = CreateInfoFrame("", "The submarine moves up and down by pumping water in and out of the two ballast tanks at the bottom of the submarine. "
|
||||
+ "The engine at the back of the sub moves it forwards and backwards.", hasButton: true);
|
||||
|
||||
while (infoBox != null)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "Steer the submarine downwards, heading further into the cavern.");
|
||||
|
||||
while (Submarine.MainSub.WorldPosition.Y > 32000.0f)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
|
||||
var moloch = Character.Create("moloch", steering.Item.WorldPosition + new Vector2(3000.0f, -500.0f), "");
|
||||
|
||||
moloch.PlaySound(CharacterSound.SoundType.Attack);
|
||||
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
|
||||
infoBox = CreateInfoFrame("", "Uh-oh... Something enormous just appeared on the sonar.");
|
||||
|
||||
List<Structure> windows = new List<Structure>();
|
||||
foreach (Structure s in Structure.WallList)
|
||||
{
|
||||
if (s.CastShadow || !s.HasBody) continue;
|
||||
|
||||
if (s.Rect.Right > steering.Item.CurrentHull.Rect.Right) windows.Add(s);
|
||||
}
|
||||
|
||||
float slowdownTimer = 1.0f;
|
||||
bool broken = false;
|
||||
do
|
||||
{
|
||||
steering.TargetVelocity = Vector2.Zero;
|
||||
|
||||
slowdownTimer = Math.Max(0.0f, slowdownTimer - CoroutineManager.DeltaTime * 0.3f);
|
||||
Submarine.MainSub.Velocity *= slowdownTimer;
|
||||
|
||||
moloch.AIController.SelectTarget(steering.Item.CurrentHull.AiTarget);
|
||||
Vector2 steeringDir = windows[0].WorldPosition - moloch.WorldPosition;
|
||||
if (steeringDir != Vector2.Zero) steeringDir = Vector2.Normalize(steeringDir);
|
||||
|
||||
moloch.AIController.SteeringManager.SteeringManual(CoroutineManager.DeltaTime, steeringDir * 100.0f);
|
||||
|
||||
foreach (Structure window in windows)
|
||||
{
|
||||
for (int i = 0; i < window.SectionCount; i++)
|
||||
{
|
||||
if (!window.SectionIsLeaking(i)) continue;
|
||||
broken = true;
|
||||
break;
|
||||
}
|
||||
if (broken) break;
|
||||
}
|
||||
if (broken) break;
|
||||
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
} while (!broken);
|
||||
|
||||
//fix everything except the command windows
|
||||
foreach (Structure w in Structure.WallList)
|
||||
{
|
||||
bool isWindow = windows.Contains(w);
|
||||
|
||||
for (int i = 0; i < w.SectionCount; i++)
|
||||
{
|
||||
if (!w.SectionIsLeaking(i)) continue;
|
||||
|
||||
if (isWindow)
|
||||
{
|
||||
//decrease window damage to slow down the leaking
|
||||
w.AddDamage(i, -w.SectionDamage(i) * 0.48f);
|
||||
}
|
||||
else
|
||||
{
|
||||
w.AddDamage(i, -100000.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Submarine.MainSub.GodMode = true;
|
||||
|
||||
var capacitor1 = Item.ItemList.Find(i => i.HasTag("capacitor1")).GetComponent<PowerContainer>();
|
||||
var capacitor2 = Item.ItemList.Find(i => i.HasTag("capacitor1")).GetComponent<PowerContainer>();
|
||||
CoroutineManager.StartCoroutine(KeepEnemyAway(moloch, new PowerContainer[] { capacitor1, capacitor2 }));
|
||||
|
||||
infoBox = CreateInfoFrame("", "The hull has been breached! Close all the doors to the command room to stop the water from flooding the entire sub!");
|
||||
|
||||
Door commandDoor1 = Item.ItemList.Find(i => i.HasTag("commanddoor1")).GetComponent<Door>();
|
||||
Door commandDoor2 = Item.ItemList.Find(i => i.HasTag("commanddoor2")).GetComponent<Door>();
|
||||
|
||||
//wait until the player is out of the room and the doors are closed
|
||||
while (Controlled.WorldPosition.X > commandDoor1.Item.WorldPosition.X ||
|
||||
(commandDoor1.IsOpen || commandDoor2.IsOpen))
|
||||
{
|
||||
//prevent the hull from filling up completely and crushing the player
|
||||
steering.Item.CurrentHull.WaterVolume = Math.Min(steering.Item.CurrentHull.WaterVolume, steering.Item.CurrentHull.Volume * 0.9f);
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
|
||||
infoBox = CreateInfoFrame("", "You should quickly find yourself a diving mask or a diving suit. " +
|
||||
"There are some in the room next to the airlock.");
|
||||
|
||||
bool divingMaskSelected = false;
|
||||
|
||||
while (!HasItem("divingmask") && !HasItem("divingsuit"))
|
||||
{
|
||||
if (!divingMaskSelected &&
|
||||
Controlled.FocusedItem != null && Controlled.FocusedItem.Prefab.Identifier == "divingsuit")
|
||||
{
|
||||
infoBox = CreateInfoFrame("", "There can only be one item in each inventory slot, so you need to take off "
|
||||
+ "the jumpsuit if you wish to wear a diving suit.");
|
||||
|
||||
divingMaskSelected = true;
|
||||
}
|
||||
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
if (HasItem("divingmask"))
|
||||
{
|
||||
infoBox = CreateInfoFrame("", "The diving mask will let you breathe underwater, but it won't protect from the water pressure outside the sub. " +
|
||||
"It should be fine for the situation at hand, but you still need to find an oxygen tank and drag it into the same slot as the mask." +
|
||||
"You should grab one or two from one of the cabinets.");
|
||||
}
|
||||
else if (HasItem("divingsuit"))
|
||||
{
|
||||
infoBox = CreateInfoFrame("", "In addition to letting you breathe underwater, the suit will protect you from the water pressure outside the sub " +
|
||||
"(unlike the diving mask). However, you still need to drag an oxygen tank into the same slot as the suit to supply oxygen. " +
|
||||
"You should grab one or two from one of the cabinets.");
|
||||
}
|
||||
|
||||
while (!HasItem("oxygentank"))
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(5.0f);
|
||||
|
||||
infoBox = CreateInfoFrame("", "Now you should stop the creature attacking the submarine before it does any more damage. Head to the railgun room at the upper right corner of the sub.");
|
||||
|
||||
var railGun = Item.ItemList.Find(i => i.GetComponent<Turret>() != null);
|
||||
|
||||
while (Vector2.Distance(Controlled.Position, railGun.Position) > 500)
|
||||
{
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "The railgun requires a large power surge to fire. The reactor can't provide a surge large enough, so we need to use the "
|
||||
+ " supercapacitors in the railgun room. The capacitors need to be charged first; select them and crank up the recharge rate.");
|
||||
|
||||
while (capacitor1.RechargeSpeed < 0.5f && capacitor2.RechargeSpeed < 0.5f)
|
||||
{
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "The capacitors take some time to recharge, so now is a good " +
|
||||
"time to head to the room below and load some shells for the railgun.");
|
||||
|
||||
|
||||
var loader = Item.ItemList.Find(i => i.Prefab.Identifier == "railgunloader").GetComponent<ItemContainer>();
|
||||
|
||||
while (Math.Abs(Controlled.Position.Y - loader.Item.Position.Y) > 80)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "Grab one of the shells. You can load it by selecting the railgun loader and dragging the shell to. "
|
||||
+ "one of the free slots. You need two hands to carry a shell, so make sure you don't have anything else in either hand.");
|
||||
|
||||
while (loader.Item.ContainedItems.FirstOrDefault(i => i != null && i.Prefab.Identifier == "railgunshell") == null)
|
||||
{
|
||||
//TODO: reimplement
|
||||
//moloch.Health = 50.0f;
|
||||
|
||||
capacitor1.Charge += 5.0f;
|
||||
capacitor2.Charge += 5.0f;
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "Now we're ready to shoot! Select the railgun controller.");
|
||||
|
||||
while (Controlled.SelectedConstruction == null || Controlled.SelectedConstruction.Prefab.Identifier != "railguncontroller")
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
moloch.AnimController.SetPosition(ConvertUnits.ToSimUnits(Controlled.WorldPosition + Vector2.UnitY * 600.0f));
|
||||
|
||||
infoBox = CreateInfoFrame("", "Use the right mouse button to aim and wait for the creature to come closer. When you're ready to shoot, "
|
||||
+ "press the left mouse button.");
|
||||
|
||||
while (!moloch.IsDead)
|
||||
{
|
||||
if (moloch.WorldPosition.Y > Controlled.WorldPosition.Y + 600.0f)
|
||||
{
|
||||
moloch.AIController.SteeringManager.SteeringManual(CoroutineManager.DeltaTime, Controlled.WorldPosition - moloch.WorldPosition);
|
||||
}
|
||||
|
||||
moloch.AIController.SelectTarget(Controlled.AiTarget);
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
Submarine.MainSub.GodMode = false;
|
||||
|
||||
infoBox = CreateInfoFrame("", "The creature has died. Now you should fix the damages in the control room: " +
|
||||
"Grab a welding tool from the closet in the railgun room.");
|
||||
|
||||
while (!HasItem("weldingtool"))
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "The welding tool requires fuel to work. Grab a welding fuel tank and attach it to the tool " +
|
||||
"by dragging it into the same slot.");
|
||||
|
||||
do
|
||||
{
|
||||
var weldingTool = Controlled.Inventory.FindItemByIdentifier("weldingtool");
|
||||
if (weldingTool != null &&
|
||||
weldingTool.ContainedItems.FirstOrDefault(contained => contained != null && contained.Prefab.Identifier == "weldingfueltank") != null) break;
|
||||
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
} while (true);
|
||||
|
||||
|
||||
infoBox = CreateInfoFrame("", "You can aim with the tool using the right mouse button and weld using the left button. " +
|
||||
"Head to the command room to fix the leaks there.");
|
||||
|
||||
do
|
||||
{
|
||||
broken = false;
|
||||
foreach (Structure window in windows)
|
||||
{
|
||||
for (int i = 0; i < window.SectionCount; i++)
|
||||
{
|
||||
if (!window.SectionIsLeaking(i)) continue;
|
||||
broken = true;
|
||||
break;
|
||||
}
|
||||
if (broken) break;
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
} while (broken);
|
||||
|
||||
infoBox = CreateInfoFrame("", "The hull is fixed now, but there's still quite a bit of water inside the sub. It should be pumped out "
|
||||
+ "using the bilge pump in the room at the bottom of the submarine.");
|
||||
|
||||
Pump pump = Item.ItemList.Find(i => i.HasTag("tutorialpump")).GetComponent<Pump>();
|
||||
|
||||
while (Vector2.Distance(Controlled.Position, pump.Item.Position) > 100.0f)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "The two pumps inside the ballast tanks "
|
||||
+ "are connected straight to the navigation terminal and can't be manually controlled unless you mess with their wiring, " +
|
||||
"so you should only use the pump in the middle room to pump out the water. Select it, turn it on and adjust the pumping speed " +
|
||||
"to start pumping water out.", hasButton: true);
|
||||
|
||||
while (infoBox != null)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
|
||||
bool brokenMsgShown = false;
|
||||
|
||||
Item brokenBox = null;
|
||||
|
||||
while (pump.FlowPercentage > 0.0f || pump.CurrFlow <= 0.0f || !pump.IsActive)
|
||||
{
|
||||
if (!brokenMsgShown && pump.Voltage < pump.MinVoltage && Controlled.SelectedConstruction == pump.Item)
|
||||
{
|
||||
brokenMsgShown = true;
|
||||
|
||||
infoBox = CreateInfoFrame("", "Looks like the pump isn't getting any power. The water must have short-circuited some of the junction "
|
||||
+ "boxes. You can check which boxes are broken by selecting them.");
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (Controlled.SelectedConstruction!=null &&
|
||||
Controlled.SelectedConstruction.GetComponent<PowerTransfer>() != null &&
|
||||
Controlled.SelectedConstruction.Condition == 0.0f)
|
||||
{
|
||||
brokenBox = Controlled.SelectedConstruction;
|
||||
|
||||
infoBox = CreateInfoFrame("", "Here's our problem: this junction box is broken. Luckily engineers are adept at fixing electrical devices - "
|
||||
+ "you just need to find a spare wire and click the \"Fix\"-button to repair the box.");
|
||||
break;
|
||||
}
|
||||
|
||||
if (pump.Voltage > pump.MinVoltage) break;
|
||||
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
}
|
||||
|
||||
if (brokenBox != null && brokenBox.ConditionPercentage > 50.0f && pump.Voltage < pump.MinVoltage)
|
||||
{
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
|
||||
if (pump.Voltage < pump.MinVoltage)
|
||||
{
|
||||
infoBox = CreateInfoFrame("", "The pump is still not running. Check if there are more broken junction boxes between the pump and the reactor.");
|
||||
}
|
||||
brokenBox = null;
|
||||
}
|
||||
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "The pump is up and running. Wait for the water to be drained out.");
|
||||
|
||||
while (pump.Item.CurrentHull.WaterVolume > 1000.0f)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "That was all there is to this tutorial! Now you should be able to handle " +
|
||||
"most of the basic tasks on board the submarine.");
|
||||
|
||||
Completed = true;
|
||||
|
||||
yield return new WaitForSeconds(4.0f);
|
||||
|
||||
Controlled = null;
|
||||
GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
|
||||
GameMain.LightManager.LosEnabled = false;
|
||||
|
||||
var cinematic = new CameraTransition(Submarine.MainSub, GameMain.GameScreen.Cam, Alignment.CenterLeft, Alignment.CenterRight, panDuration: 5.0f);
|
||||
|
||||
while (cinematic.Running)
|
||||
{
|
||||
yield return Controlled != null && Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
Submarine.Unload();
|
||||
GameMain.MainMenuScreen.Select();
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
private bool HasItem(string itemIdentifier)
|
||||
{
|
||||
if (Character.Controlled == null) return false;
|
||||
|
||||
return Character.Controlled.Inventory.FindItemByIdentifier(itemIdentifier) != null;
|
||||
}
|
||||
|
||||
protected IEnumerable<CoroutineStatus> KeepReactorRunning(Reactor reactor)
|
||||
{
|
||||
do
|
||||
{
|
||||
//TODO: reimplement
|
||||
/*reactor.AutoTemp = true;
|
||||
reactor.ShutDownTemp = 5000.0f;*/
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
} while (Item.ItemList.Contains(reactor.Item));
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// keeps the enemy away from the sub until the capacitors are loaded
|
||||
/// </summary>
|
||||
private IEnumerable<CoroutineStatus> KeepEnemyAway(Character enemy, PowerContainer[] capacitors)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (enemy == null || Character.Controlled == null) break;
|
||||
|
||||
//TODO: reimplement
|
||||
//enemy.Health = 50.0f;
|
||||
|
||||
if (enemy.AIController is EnemyAIController enemyAI)
|
||||
{
|
||||
enemyAI.State = AIState.Idle;
|
||||
}
|
||||
|
||||
Vector2 targetPos = Character.Controlled.WorldPosition + new Vector2(0.0f, 3000.0f);
|
||||
|
||||
Vector2 steering = targetPos - enemy.WorldPosition;
|
||||
if (steering != Vector2.Zero) steering = Vector2.Normalize(steering);
|
||||
|
||||
enemy.AIController.Steering = steering;
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
} while (capacitors.FirstOrDefault(c => c.Charge > 0.4f) == null);
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -41,30 +41,79 @@ namespace Barotrauma.Tutorials
|
||||
|
||||
// Variables
|
||||
private Character captain;
|
||||
private string radioSpeakerName;
|
||||
private LocalizedString radioSpeakerName;
|
||||
private Sprite captain_steerIcon;
|
||||
private Color captain_steerIconColor;
|
||||
|
||||
public CaptainTutorial(XElement element) : base(element)
|
||||
public CaptainTutorial() : base("tutorial.captaintraining".ToIdentifier(),
|
||||
new Segment(
|
||||
"Captain.CommandMedic".ToIdentifier(),
|
||||
"Captain.CommandMedicObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Captain.CommandMedicText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_command.webm", TextTag = "Captain.CommandMedicText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Captain.CommandMechanic".ToIdentifier(),
|
||||
"Captain.CommandMechanicObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Captain.CommandMechanicText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Captain.CommandSecurity".ToIdentifier(),
|
||||
"Captain.CommandSecurityObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Captain.CommandSecurityText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Captain.CommandEngineer".ToIdentifier(),
|
||||
"Captain.CommandEngineerObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Captain.CommandEngineerText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Captain.Undock".ToIdentifier(),
|
||||
"Captain.UndockObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Captain.UndockText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_undock.webm", TextTag = "Captain.UndockText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Captain.Navigate".ToIdentifier(),
|
||||
"Captain.NavigateObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Captain.NavigateText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_navigation.webm", TextTag = "Captain.NavigateText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Captain.Dock".ToIdentifier(),
|
||||
"Captain.DockObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Captain.DockText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_docking.webm", TextTag = "Captain.DockText".ToIdentifier(), Width = 450, Height = 80 }))
|
||||
{ }
|
||||
|
||||
protected override CharacterInfo GetCharacterInfo()
|
||||
{
|
||||
return new CharacterInfo(
|
||||
CharacterPrefab.HumanSpeciesName,
|
||||
jobOrJobPrefab: new Job(
|
||||
JobPrefab.Prefabs["captain"], Rand.RandSync.Unsynced, 0,
|
||||
new Skill("medical".ToIdentifier(), 20),
|
||||
new Skill("weapons".ToIdentifier(), 20),
|
||||
new Skill("mechanical".ToIdentifier(), 20),
|
||||
new Skill("electrical".ToIdentifier(), 20),
|
||||
new Skill("helm".ToIdentifier(), 70)));
|
||||
}
|
||||
|
||||
public override void Start()
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
captain = Character.Controlled;
|
||||
radioSpeakerName = TextManager.Get("Tutorial.Radio.Watchman");
|
||||
GameMain.GameSession.CrewManager.AllowCharacterSwitch = false;
|
||||
|
||||
var revolver = FindOrGiveItem(captain, "revolver");
|
||||
var revolver = FindOrGiveItem(captain, "revolver".ToIdentifier());
|
||||
revolver.Unequip(captain);
|
||||
captain.Inventory.RemoveItem(revolver);
|
||||
|
||||
var captainscap =
|
||||
captain.Inventory.FindItemByIdentifier("captainscap1") ??
|
||||
captain.Inventory.FindItemByIdentifier("captainscap2") ??
|
||||
captain.Inventory.FindItemByIdentifier("captainscap3");
|
||||
captain.Inventory.FindItemByIdentifier("captainscap1".ToIdentifier()) ??
|
||||
captain.Inventory.FindItemByIdentifier("captainscap2".ToIdentifier()) ??
|
||||
captain.Inventory.FindItemByIdentifier("captainscap3".ToIdentifier());
|
||||
|
||||
if (captainscap != null)
|
||||
{
|
||||
@@ -73,16 +122,16 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
|
||||
var captainsuniform =
|
||||
captain.Inventory.FindItemByIdentifier("captainsuniform1") ??
|
||||
captain.Inventory.FindItemByIdentifier("captainsuniform2") ??
|
||||
captain.Inventory.FindItemByIdentifier("captainsuniform3");
|
||||
captain.Inventory.FindItemByIdentifier("captainsuniform1".ToIdentifier()) ??
|
||||
captain.Inventory.FindItemByIdentifier("captainsuniform2".ToIdentifier()) ??
|
||||
captain.Inventory.FindItemByIdentifier("captainsuniform3".ToIdentifier());
|
||||
if (captainsuniform != null)
|
||||
{
|
||||
captainsuniform.Unequip(captain);
|
||||
captain.Inventory.RemoveItem(captainsuniform);
|
||||
}
|
||||
|
||||
var steerOrder = Order.GetPrefab("steer");
|
||||
var steerOrder = OrderPrefab.Prefabs["steer"];
|
||||
captain_steerIcon = steerOrder.SymbolSprite;
|
||||
captain_steerIconColor = steerOrder.Color;
|
||||
|
||||
@@ -99,7 +148,7 @@ namespace Barotrauma.Tutorials
|
||||
captain_medicSpawnPos = Item.ItemList.Find(i => i.HasTag("captain_medicspawnpos")).WorldPosition;
|
||||
tutorial_submarineDoor = Item.ItemList.Find(i => i.HasTag("tutorial_submarinedoor")).GetComponent<Door>();
|
||||
tutorial_submarineDoorLight = Item.ItemList.Find(i => i.HasTag("tutorial_submarinedoorlight")).GetComponent<LightComponent>();
|
||||
var medicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("medicaldoctor"));
|
||||
var medicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("medicaldoctor"));
|
||||
captain_medic = Character.Create(medicInfo, captain_medicSpawnPos, "medicaldoctor");
|
||||
captain_medic.TeamID = CharacterTeamType.Team1;
|
||||
captain_medic.GiveJobItems(null);
|
||||
@@ -122,17 +171,17 @@ namespace Barotrauma.Tutorials
|
||||
SetDoorAccess(tutorial_lockedDoor_1, null, false);
|
||||
SetDoorAccess(tutorial_lockedDoor_2, null, false);
|
||||
|
||||
var mechanicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("mechanic"));
|
||||
var mechanicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("mechanic"));
|
||||
captain_mechanic = Character.Create(mechanicInfo, WayPoint.GetRandom(SpawnType.Human, mechanicInfo.Job?.Prefab, Submarine.MainSub).WorldPosition, "mechanic");
|
||||
captain_mechanic.TeamID = CharacterTeamType.Team1;
|
||||
captain_mechanic.GiveJobItems();
|
||||
|
||||
var securityInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("securityofficer"));
|
||||
var securityInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("securityofficer"));
|
||||
captain_security = Character.Create(securityInfo, WayPoint.GetRandom(SpawnType.Human, securityInfo.Job?.Prefab, Submarine.MainSub).WorldPosition, "securityofficer");
|
||||
captain_security.TeamID = CharacterTeamType.Team1;
|
||||
captain_security.GiveJobItems();
|
||||
|
||||
var engineerInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("engineer"));
|
||||
var engineerInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("engineer"));
|
||||
captain_engineer = Character.Create(engineerInfo, WayPoint.GetRandom(SpawnType.Human, engineerInfo.Job?.Prefab, Submarine.MainSub).WorldPosition, "engineer");
|
||||
captain_engineer.TeamID = CharacterTeamType.Team1;
|
||||
captain_engineer.GiveJobItems();
|
||||
@@ -163,7 +212,7 @@ namespace Barotrauma.Tutorials
|
||||
yield return new WaitForSeconds(2f, false);
|
||||
GameMain.GameSession.CrewManager.AutoShowCrewList();
|
||||
GameMain.GameSession.CrewManager.AddCharacter(captain_medic);
|
||||
TriggerTutorialSegment(0, GameMain.Config.KeyBindText(InputType.Command));
|
||||
TriggerTutorialSegment(0, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Command));
|
||||
do
|
||||
{
|
||||
yield return null;
|
||||
@@ -172,13 +221,13 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
while (!HasOrder(captain_medic, "follow"));
|
||||
SetDoorAccess(tutorial_submarineDoor, tutorial_submarineDoorLight, true);
|
||||
RemoveCompletedObjective(segments[0]);
|
||||
RemoveCompletedObjective(0);
|
||||
|
||||
// Submarine
|
||||
do { yield return null; } while (!captain_enteredSubmarineSensor.MotionDetected);
|
||||
yield return new WaitForSeconds(3f, false);
|
||||
captain_mechanic.AIController.Enabled = captain_security.AIController.Enabled = captain_engineer.AIController.Enabled = true;
|
||||
TriggerTutorialSegment(1, GameMain.Config.KeyBindText(InputType.Command));
|
||||
TriggerTutorialSegment(1, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Command));
|
||||
GameMain.GameSession.CrewManager.AddCharacter(captain_mechanic);
|
||||
do
|
||||
{
|
||||
@@ -187,9 +236,9 @@ namespace Barotrauma.Tutorials
|
||||
// GameMain.GameSession.CrewManager.HighlightOrderButton(captain_mechanic, "repairsystems", highlightColor, new Vector2(5, 5));
|
||||
//HighlightOrderOption("jobspecific");
|
||||
} while (!HasOrder(captain_mechanic, "repairsystems") && !HasOrder(captain_mechanic, "repairmechanical") && !HasOrder(captain_mechanic, "repairelectrical"));
|
||||
RemoveCompletedObjective(segments[1]);
|
||||
RemoveCompletedObjective(1);
|
||||
yield return new WaitForSeconds(2f, false);
|
||||
TriggerTutorialSegment(2, GameMain.Config.KeyBindText(InputType.Command));
|
||||
TriggerTutorialSegment(2, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Command));
|
||||
GameMain.GameSession.CrewManager.AddCharacter(captain_security);
|
||||
do
|
||||
{
|
||||
@@ -199,9 +248,9 @@ namespace Barotrauma.Tutorials
|
||||
HighlightOrderOption("fireatwill");
|
||||
}
|
||||
while (!HasOrder(captain_security, "operateweapons"));
|
||||
RemoveCompletedObjective(segments[2]);
|
||||
RemoveCompletedObjective(2);
|
||||
yield return new WaitForSeconds(4f, false);
|
||||
TriggerTutorialSegment(3, GameMain.Config.KeyBindText(InputType.Command));
|
||||
TriggerTutorialSegment(3, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Command));
|
||||
GameMain.GameSession.CrewManager.AddCharacter(captain_engineer);
|
||||
do
|
||||
{
|
||||
@@ -211,7 +260,7 @@ namespace Barotrauma.Tutorials
|
||||
HighlightOrderOption("powerup");
|
||||
}
|
||||
while (!HasOrder(captain_engineer, "operatereactor", "powerup"));
|
||||
RemoveCompletedObjective(segments[3]);
|
||||
RemoveCompletedObjective(3);
|
||||
tutorial_submarineReactor.CanBeSelected = true;
|
||||
do { yield return null; } while (!tutorial_submarineReactor.IsActive); // Wait until reactor on
|
||||
TriggerTutorialSegment(4);
|
||||
@@ -226,7 +275,7 @@ namespace Barotrauma.Tutorials
|
||||
yield return new WaitForSeconds(1.0f, false);
|
||||
} while (Submarine.MainSub.DockedTo.Any());
|
||||
captain_navConsole.UseAutoDocking = false;
|
||||
RemoveCompletedObjective(segments[4]);
|
||||
RemoveCompletedObjective(4);
|
||||
yield return new WaitForSeconds(2f, false);
|
||||
TriggerTutorialSegment(5); // Navigate to destination
|
||||
do
|
||||
@@ -241,7 +290,7 @@ namespace Barotrauma.Tutorials
|
||||
yield return null;
|
||||
} while (captain_sonar.CurrentMode != Sonar.Mode.Active);
|
||||
do { yield return null; } while (Vector2.Distance(Submarine.MainSub.WorldPosition, Level.Loaded.EndPosition) > 4000f);
|
||||
RemoveCompletedObjective(segments[5]);
|
||||
RemoveCompletedObjective(5);
|
||||
captain_navConsole.UseAutoDocking = true;
|
||||
yield return new WaitForSeconds(4f, false);
|
||||
TriggerTutorialSegment(6); // Docking
|
||||
@@ -250,7 +299,7 @@ namespace Barotrauma.Tutorials
|
||||
//captain_navConsoleCustomInterface.HighlightElement(0, uiHighlightColor, duration: 1.0f, pulsateAmount: 0.0f);
|
||||
yield return new WaitForSeconds(1.0f, false);
|
||||
} while (!Submarine.MainSub.AtEndExit || !Submarine.MainSub.DockedTo.Any());
|
||||
RemoveCompletedObjective(segments[6]);
|
||||
RemoveCompletedObjective(6);
|
||||
yield return new WaitForSeconds(3f, false);
|
||||
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.GetWithVariable("Captain.Radio.Complete", "[OUTPOSTNAME]", GameMain.GameSession.EndLocation.Name), ChatMessageType.Radio, null);
|
||||
SetHighlight(captain_navConsole.Item, false);
|
||||
|
||||
@@ -1,520 +0,0 @@
|
||||
/*using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Barotrauma.Items.Components;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma.Tutorials
|
||||
{
|
||||
class ContextualTutorial : Tutorial
|
||||
{
|
||||
public ContextualTutorial(XElement element) : base(element)
|
||||
{
|
||||
//Name = "ContextualTutorial";
|
||||
}
|
||||
|
||||
public static bool Selected = false;
|
||||
|
||||
private Steering navConsole;
|
||||
private Reactor reactor;
|
||||
private Sonar sonar;
|
||||
private Vector2 subStartingPosition;
|
||||
private List<Character> crew;
|
||||
private Character mechanic;
|
||||
private Character engineer;
|
||||
private Character injuredMember = null;
|
||||
|
||||
private List<Pair<Character, float>> characterTimeOnSonar;
|
||||
private float requiredTimeOnSonar = 5f;
|
||||
|
||||
private float tutorialTimer;
|
||||
|
||||
private bool disableTutorialOnDeficiencyFound = true;
|
||||
|
||||
private float floodTutorialTimer = 0.0f;
|
||||
private const float floodTutorialDelay = 2.0f;
|
||||
private float medicalTutorialTimer = 0.0f;
|
||||
private const float medicalTutorialDelay = 2.0f;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
for (int i = 0; i < segments.Count; i++)
|
||||
{
|
||||
segments[i].IsTriggered = false;
|
||||
}
|
||||
|
||||
characterTimeOnSonar = new List<Pair<Character, float>>();
|
||||
}
|
||||
|
||||
public void LoadPartiallyComplete(XElement element)
|
||||
{
|
||||
int[] completedSegments = element.GetAttributeIntArray("completedsegments", null);
|
||||
|
||||
if (completedSegments == null || completedSegments.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (completedSegments.Length == segments.Count) // Completed all segments
|
||||
{
|
||||
Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < completedSegments.Length; i++)
|
||||
{
|
||||
segments[completedSegments[i]].IsTriggered = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void SavePartiallyComplete(XElement element)
|
||||
{
|
||||
XElement tutorialElement = new XElement("contextualtutorial");
|
||||
tutorialElement.Add(new XAttribute("completedsegments", GetCompletedSegments()));
|
||||
element.Add(tutorialElement);
|
||||
}
|
||||
|
||||
private string GetCompletedSegments()
|
||||
{
|
||||
string completedSegments = string.Empty;
|
||||
|
||||
for (int i = 0; i < segments.Count; i++)
|
||||
{
|
||||
if (segments[i].IsTriggered)
|
||||
{
|
||||
completedSegments += i + ",";
|
||||
}
|
||||
}
|
||||
|
||||
if (completedSegments.Length > 0)
|
||||
{
|
||||
completedSegments = completedSegments.TrimEnd(',');
|
||||
}
|
||||
|
||||
return completedSegments;
|
||||
}
|
||||
|
||||
public override void Start()
|
||||
{
|
||||
if (!Initialized) return;
|
||||
|
||||
base.Start();
|
||||
injuredMember = null;
|
||||
activeContentSegment = null;
|
||||
tutorialTimer = floodTutorialTimer = medicalTutorialTimer = 0.0f;
|
||||
subStartingPosition = Vector2.Zero;
|
||||
characterTimeOnSonar.Clear();
|
||||
|
||||
subStartingPosition = Submarine.MainSub.WorldPosition;
|
||||
navConsole = Item.ItemList.Find(i => i.HasTag("command"))?.GetComponent<Steering>();
|
||||
sonar = navConsole?.Item.GetComponent<Sonar>();
|
||||
reactor = Item.ItemList.Find(i => i.HasTag("reactor"))?.GetComponent<Reactor>();
|
||||
|
||||
#if DEBUG
|
||||
if (reactor == null || navConsole == null || sonar == null)
|
||||
{
|
||||
infoBox = CreateInfoFrame("Error", "Submarine not compatible with the tutorial:"
|
||||
+ "\nReactor - " + (reactor != null ? "OK" : "Tag 'reactor' not found")
|
||||
+ "\nNavigation Console - " + (navConsole != null ? "OK" : "Tag 'command' not found")
|
||||
+ "\nSonar - " + (sonar != null ? "OK" : "Not found under Navigation Console"), hasButton: true);
|
||||
CoroutineManager.StartCoroutine(WaitForErrorClosed());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (disableTutorialOnDeficiencyFound)
|
||||
{
|
||||
if (reactor == null || navConsole == null || sonar == null)
|
||||
{
|
||||
Stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (navConsole == null) segments[2].IsTriggered = true; // Disable navigation console usage tutorial
|
||||
if (reactor == null) segments[5].IsTriggered = true; // Disable reactor usage tutorial
|
||||
if (sonar == null) segments[6].IsTriggered = true; // Disable enemy on sonar tutorial
|
||||
}
|
||||
|
||||
crew = GameMain.GameSession.CrewManager.GetCharacters().ToList();
|
||||
mechanic = CrewMemberWithJob("mechanic");
|
||||
engineer = CrewMemberWithJob("engineer");
|
||||
|
||||
Completed = true; // Trigger completed at start to prevent the contextual tutorial from automatically activating on starting new campaigns after this one
|
||||
started = true;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
private IEnumerable<object> WaitForErrorClosed()
|
||||
{
|
||||
while (infoBox != null) yield return null;
|
||||
Stop();
|
||||
}
|
||||
#endif
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
base.Stop();
|
||||
characterTimeOnSonar = null;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
base.Update(deltaTime);
|
||||
|
||||
if (!started || ContentRunning) return;
|
||||
|
||||
deltaTime *= 0.5f;
|
||||
|
||||
for (int i = 0; i < segments.Count; i++)
|
||||
{
|
||||
if (segments[i].IsTriggered || HasObjective(segments[i])) continue;
|
||||
if (CheckContextualTutorials(i, deltaTime)) // Found a relevant tutorial, halt finding new ones
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool CheckContextualTutorials(int index, float deltaTime)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0: // Welcome: Game Start [Text]
|
||||
if (tutorialTimer < 1.0f)
|
||||
{
|
||||
tutorialTimer += deltaTime;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 1: // Command Reactor: 2 seconds after 'Welcome' dismissed and only if no command given to start reactor [Video]
|
||||
if (!segments[0].IsTriggered) return false;
|
||||
if (tutorialTimer < 3.0f)
|
||||
{
|
||||
tutorialTimer += deltaTime;
|
||||
|
||||
if (HasOrder("operatereactor"))
|
||||
{
|
||||
segments[index].IsTriggered = true;
|
||||
tutorialTimer = 2.5f;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 2: // Nav Console: 2 seconds after 'Command Reactor' dismissed or if nav console is activated [Video]
|
||||
if (!IsReactorPoweredUp()) return false; // Do not advance tutorial based on this segment if reactor has not been powered up
|
||||
if (Character.Controlled?.SelectedConstruction != navConsole.Item)
|
||||
{
|
||||
if (tutorialTimer < 4.5f)
|
||||
{
|
||||
tutorialTimer += deltaTime;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tutorialTimer = 4.5f;
|
||||
}
|
||||
|
||||
TriggerTutorialSegment(index, GameMain.GameSession.EndLocation.Name);
|
||||
return true;
|
||||
case 3: // Objective: Travel ~150 meters and while sub is not flooding [Text]
|
||||
if (Vector2.Distance(subStartingPosition, Submarine.MainSub.WorldPosition) < 8000f || IsFlooding())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else // Called earlier than others due to requiring specific args
|
||||
{
|
||||
TriggerTutorialSegment(index, GameMain.GameSession.EndLocation.Name);
|
||||
return true;
|
||||
}
|
||||
case 4: // Flood: Hull is breached and sub is taking on water [Video]
|
||||
if (!IsFlooding())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (floodTutorialTimer < floodTutorialDelay)
|
||||
{
|
||||
floodTutorialTimer += deltaTime;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 5: // Reactor: Player uses reactor for the first time [Video]
|
||||
if (Character.Controlled?.SelectedConstruction != reactor.Item)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 6: // Enemy on Sonar: Player witnesses creature signal on sonar for 5 seconds [Video]
|
||||
if (!HasEnemyOnSonarForDuration(deltaTime))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 7: // Degrading1: Any equipment degrades to 50% health or less and player has not assigned any crew to perform maintenance [Text]
|
||||
if ((mechanic == null || mechanic.IsDead) && (engineer == null || engineer.IsDead)) // Both engineer and mechanic are dead or do not exist -> do not display
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool degradedEquipmentFound = false;
|
||||
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
if (!item.Repairables.Any() || item.Condition > 50.0f) continue;
|
||||
degradedEquipmentFound = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (degradedEquipmentFound)
|
||||
{
|
||||
if (HasOrder("repairsystems", "jobspecific"))
|
||||
{
|
||||
segments[index].IsTriggered = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 8: // Medical: Crewmember is injured but not killed [Video]
|
||||
|
||||
if (injuredMember == null)
|
||||
{
|
||||
for (int i = 0; i < crew.Count; i++)
|
||||
{
|
||||
Character member = crew[i];
|
||||
if (member.Vitality < member.MaxVitality && !member.IsDead)
|
||||
{
|
||||
injuredMember = member;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else if (medicalTutorialTimer < medicalTutorialDelay)
|
||||
{
|
||||
medicalTutorialTimer += deltaTime;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
TriggerTutorialSegment(index, new string[] { injuredMember.Info.DisplayName,
|
||||
(injuredMember.Info.Gender == Gender.Male) ? TextManager.Get("PronounPossessiveMale").ToLower() : TextManager.Get("PronounPossessiveFemale").ToLower() });
|
||||
return true;
|
||||
}
|
||||
case 9: // Approach1: Destination is within ~100m [Video]
|
||||
if (Vector2.Distance(Submarine.MainSub.WorldPosition, Level.Loaded.EndPosition) > 8000f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
TriggerTutorialSegment(index, GameMain.GameSession.EndLocation.Name);
|
||||
return true;
|
||||
}
|
||||
case 10: // Approach2: Sub is docked [Text]
|
||||
if (!Submarine.MainSub.AtEndPosition || Submarine.MainSub.DockedTo.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
TriggerTutorialSegment(index);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void CheckActiveObjectives(TutorialSegment objective, float deltaTime)
|
||||
{
|
||||
switch(objective.Id)
|
||||
{
|
||||
case "ReactorCommand": // Reactor commanded
|
||||
if (!IsReactorPoweredUp())
|
||||
{
|
||||
if (!HasOrder("operatereactor")) return;
|
||||
}
|
||||
break;
|
||||
case "NavConsole": // traveled 50 meters
|
||||
if (Vector2.Distance(subStartingPosition, Submarine.MainSub.WorldPosition) < 4000f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case "Flood": // Hull breaches repaired
|
||||
if (IsFlooding()) return;
|
||||
break;
|
||||
case "Medical":
|
||||
if (injuredMember != null && !injuredMember.IsDead)
|
||||
{
|
||||
if (injuredMember.CharacterHealth.DroppedItem == null) return;
|
||||
}
|
||||
break;
|
||||
case "EnemyOnSonar": // Enemy dispatched
|
||||
if (HasEnemyOnSonarForDuration(deltaTime))
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case "Degrading": // Fixed
|
||||
if (mechanic != null && !mechanic.IsDead)
|
||||
{
|
||||
HumanAIController humanAI = mechanic.AIController as HumanAIController;
|
||||
if (mechanic.CurrentOrder?.AITag != "repairsystems" || humanAI.CurrentOrderOption != "jobspecific")
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (engineer != null && !engineer.IsDead)
|
||||
{
|
||||
HumanAIController humanAI = engineer.AIController as HumanAIController;
|
||||
if (engineer.CurrentOrder?.AITag != "repairsystems" || humanAI.CurrentOrderOption != "jobspecific")
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case "Approach1": // Wait until docked
|
||||
if (!Submarine.MainSub.AtEndPosition || Submarine.MainSub.DockedTo.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
RemoveCompletedObjective(objective);
|
||||
}
|
||||
|
||||
private bool IsReactorPoweredUp()
|
||||
{
|
||||
float load = 0.0f;
|
||||
List<Connection> connections = reactor.Item.Connections;
|
||||
if (connections != null && connections.Count > 0)
|
||||
{
|
||||
foreach (Connection connection in connections)
|
||||
{
|
||||
if (!connection.IsPower) continue;
|
||||
foreach (Connection recipient in connection.Recipients)
|
||||
{
|
||||
if (!(recipient.Item is Item it)) continue;
|
||||
|
||||
PowerTransfer pt = it.GetComponent<PowerTransfer>();
|
||||
if (pt == null) continue;
|
||||
|
||||
load = Math.Max(load, pt.PowerLoad);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Math.Abs(load + reactor.CurrPowerConsumption) < 10;
|
||||
}
|
||||
|
||||
private Character CrewMemberWithJob(string job)
|
||||
{
|
||||
job = job.ToLowerInvariant();
|
||||
for (int i = 0; i < crew.Count; i++)
|
||||
{
|
||||
if (crew[i].Info.Job.Prefab.Identifier.ToLowerInvariant() == job) return crew[i];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private bool HasOrder(string aiTag, string option = null)
|
||||
{
|
||||
for (int i = 0; i < crew.Count; i++)
|
||||
{
|
||||
if (crew[i].CurrentOrder?.AITag == aiTag)
|
||||
{
|
||||
if (option == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
HumanAIController humanAI = crew[i].AIController as HumanAIController;
|
||||
return humanAI.CurrentOrderOption == option;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsFlooding()
|
||||
{
|
||||
foreach (Gap gap in Gap.GapList)
|
||||
{
|
||||
if (gap.ConnectedWall == null || gap.IsRoomToRoom) continue;
|
||||
if (gap.ConnectedDoor != null || gap.Open <= 0.0f) continue;
|
||||
if (gap.Submarine == null) continue;
|
||||
if (gap.Submarine.IsOutpost) continue;
|
||||
if (gap.Submarine != Submarine.MainSub) continue;
|
||||
if (gap.FlowTargetHull == null || gap.FlowTargetHull.WaterPercentage <= 0.0f) continue;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool HasEnemyOnSonarForDuration(float deltaTime)
|
||||
{
|
||||
foreach (Character c in Character.CharacterList)
|
||||
{
|
||||
if (c.AnimController.CurrentHull != null || !c.Enabled || !(c.AIController is EnemyAIController)) continue;
|
||||
if (sonar.DetectSubmarineWalls && c.AnimController.CurrentHull == null && sonar.Item.CurrentHull != null) continue;
|
||||
if (Vector2.DistanceSquared(c.WorldPosition, sonar.Item.WorldPosition) > sonar.Range * sonar.Range)
|
||||
{
|
||||
for (int i = 0; i < characterTimeOnSonar.Count; i++)
|
||||
{
|
||||
if (characterTimeOnSonar[i].First == c)
|
||||
{
|
||||
characterTimeOnSonar.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
Pair<Character, float> pair = characterTimeOnSonar.Find(ct => ct.First == c);
|
||||
if (pair != null)
|
||||
{
|
||||
pair.Second += deltaTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
characterTimeOnSonar.Add(new Pair<Character, float>(c, deltaTime));
|
||||
}
|
||||
}
|
||||
|
||||
return characterTimeOnSonar.Find(ct => ct.Second >= requiredTimeOnSonar && !ct.First.IsDead) != null;
|
||||
}
|
||||
|
||||
protected override void TriggerTutorialSegment(int index, params object[] args)
|
||||
{
|
||||
base.TriggerTutorialSegment(index, args);
|
||||
|
||||
for (int i = 0; i < segments.Count; i++)
|
||||
{
|
||||
if (!segments[i].IsTriggered) return;
|
||||
}
|
||||
|
||||
CoroutineManager.StartCoroutine(WaitToStop()); // Completed
|
||||
}
|
||||
|
||||
private IEnumerable<object> WaitToStop()
|
||||
{
|
||||
while (ContentRunning) yield return null;
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
@@ -15,7 +15,7 @@ namespace Barotrauma.Tutorials
|
||||
private float shakeTimer = 1f;
|
||||
private float shakeAmount = 20f;
|
||||
|
||||
private string radioSpeakerName;
|
||||
private LocalizedString radioSpeakerName;
|
||||
private Character doctor;
|
||||
|
||||
private ItemContainer doctor_suppliesCabinet;
|
||||
@@ -40,14 +40,66 @@ namespace Barotrauma.Tutorials
|
||||
private Sprite doctor_firstAidIcon;
|
||||
private Color doctor_firstAidIconColor;
|
||||
|
||||
public DoctorTutorial(XElement element) : base(element)
|
||||
{
|
||||
}
|
||||
public override void Start()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
var firstAidOrder = Order.GetPrefab("requestfirstaid");
|
||||
public DoctorTutorial() : base("tutorial.medicaldoctortraining".ToIdentifier(),
|
||||
new Segment(
|
||||
"Doctor.Supplies".ToIdentifier(),
|
||||
"Doctor.SuppliesObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Doctor.SuppliesText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Doctor.OpenMedicalInterface".ToIdentifier(),
|
||||
"Doctor.OpenMedicalInterfaceObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Doctor.OpenMedicalInterfaceText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_medinterface1.webm", TextTag = "Doctor.OpenMedicalInterfaceText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Doctor.FirstAidSelf".ToIdentifier(),
|
||||
"Doctor.FirstAidSelfObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Doctor.FirstAidSelfText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_medinterface1.webm", TextTag = "Doctor.FirstAidSelfText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Doctor.Medbay".ToIdentifier(),
|
||||
"Doctor.MedbayObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Doctor.MedbayText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_command.webm", TextTag = "Doctor.MedbayText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Doctor.TreatBurns".ToIdentifier(),
|
||||
"Doctor.TreatBurnsObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Doctor.TreatBurnsText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_medinterface2.webm", TextTag = "Doctor.TreatBurnsText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Doctor.CPR".ToIdentifier(),
|
||||
"Doctor.CPRObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Doctor.CPRText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_cpr.webm", TextTag = "Doctor.CPRText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Doctor.Submarine".ToIdentifier(),
|
||||
"Doctor.SubmarineObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Doctor.SubmarineText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }))
|
||||
{ }
|
||||
|
||||
protected override CharacterInfo GetCharacterInfo()
|
||||
{
|
||||
return new CharacterInfo(
|
||||
CharacterPrefab.HumanSpeciesName,
|
||||
jobOrJobPrefab: new Job(
|
||||
JobPrefab.Prefabs["medicaldoctor"], Rand.RandSync.Unsynced, 0,
|
||||
new Skill("medical".ToIdentifier(), 70),
|
||||
new Skill("weapons".ToIdentifier(), 20),
|
||||
new Skill("mechanical".ToIdentifier(), 20),
|
||||
new Skill("electrical".ToIdentifier(), 20),
|
||||
new Skill("helm".ToIdentifier(), 20)));
|
||||
}
|
||||
|
||||
protected override void Initialize()
|
||||
{
|
||||
var firstAidOrder = OrderPrefab.Prefabs["requestfirstaid"];
|
||||
doctor_firstAidIcon = firstAidOrder.SymbolSprite;
|
||||
doctor_firstAidIconColor = firstAidOrder.Color;
|
||||
|
||||
@@ -55,19 +107,19 @@ namespace Barotrauma.Tutorials
|
||||
radioSpeakerName = TextManager.Get("Tutorial.Radio.Speaker");
|
||||
doctor = Character.Controlled;
|
||||
|
||||
var bandages = FindOrGiveItem(doctor, "antibleeding1");
|
||||
var bandages = FindOrGiveItem(doctor, "antibleeding1".ToIdentifier());
|
||||
bandages.Unequip(doctor);
|
||||
doctor.Inventory.RemoveItem(bandages);
|
||||
|
||||
var syringegun = FindOrGiveItem(doctor, "syringegun");
|
||||
var syringegun = FindOrGiveItem(doctor, "syringegun".ToIdentifier());
|
||||
syringegun.Unequip(doctor);
|
||||
doctor.Inventory.RemoveItem(syringegun);
|
||||
|
||||
var antibiotics = FindOrGiveItem(doctor, "antibiotics");
|
||||
var antibiotics = FindOrGiveItem(doctor, "antibiotics".ToIdentifier());
|
||||
antibiotics.Unequip(doctor);
|
||||
doctor.Inventory.RemoveItem(antibiotics);
|
||||
|
||||
var morphine = FindOrGiveItem(doctor, "antidama1");
|
||||
var morphine = FindOrGiveItem(doctor, "antidama1".ToIdentifier());
|
||||
morphine.Unequip(doctor);
|
||||
doctor.Inventory.RemoveItem(morphine);
|
||||
|
||||
@@ -78,7 +130,7 @@ namespace Barotrauma.Tutorials
|
||||
var patientHull2 = WayPoint.WayPointList.Find(wp => wp.IdCardDesc == "airlock").CurrentHull;
|
||||
medBay = WayPoint.WayPointList.Find(wp => wp.IdCardDesc == "medbay").CurrentHull;
|
||||
|
||||
var assistantInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("assistant"));
|
||||
var assistantInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("assistant"));
|
||||
patient1 = Character.Create(assistantInfo, patientHull1.WorldPosition, "1");
|
||||
patient1.TeamID = CharacterTeamType.Team1;
|
||||
patient1.GiveJobItems(null);
|
||||
@@ -86,26 +138,26 @@ namespace Barotrauma.Tutorials
|
||||
patient1.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.Burn, 15.0f) }, stun: 0, playSound: false);
|
||||
patient1.AIController.Enabled = false;
|
||||
|
||||
assistantInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("assistant"));
|
||||
assistantInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("assistant"));
|
||||
patient2 = Character.Create(assistantInfo, patientHull2.WorldPosition, "2");
|
||||
patient2.TeamID = CharacterTeamType.Team1;
|
||||
patient2.GiveJobItems(null);
|
||||
patient2.CanSpeak = false;
|
||||
patient2.AIController.Enabled = false;
|
||||
|
||||
var mechanicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("engineer"));
|
||||
var mechanicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("engineer"));
|
||||
var subPatient1 = Character.Create(mechanicInfo, WayPoint.GetRandom(SpawnType.Human, mechanicInfo.Job?.Prefab, Submarine.MainSub).WorldPosition, "3");
|
||||
subPatient1.TeamID = CharacterTeamType.Team1;
|
||||
subPatient1.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.Burn, 40.0f) }, stun: 0, playSound: false);
|
||||
subPatients.Add(subPatient1);
|
||||
|
||||
var securityInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("securityofficer"));
|
||||
var securityInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("securityofficer"));
|
||||
var subPatient2 = Character.Create(securityInfo, WayPoint.GetRandom(SpawnType.Human, securityInfo.Job?.Prefab, Submarine.MainSub).WorldPosition, "3");
|
||||
subPatient2.TeamID = CharacterTeamType.Team1;
|
||||
subPatient2.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.InternalDamage, 40.0f) }, stun: 0, playSound: false);
|
||||
subPatients.Add(subPatient2);
|
||||
|
||||
var engineerInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("engineer"));
|
||||
var engineerInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("engineer"));
|
||||
var subPatient3 = Character.Create(securityInfo, WayPoint.GetRandom(SpawnType.Human, engineerInfo.Job?.Prefab, Submarine.MainSub).WorldPosition, "3");
|
||||
subPatient3.TeamID = CharacterTeamType.Team1;
|
||||
subPatient3.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.Burn, 20.0f) }, stun: 0, playSound: false);
|
||||
@@ -196,7 +248,7 @@ namespace Barotrauma.Tutorials
|
||||
yield return new WaitForSeconds(2.0f);
|
||||
}*/
|
||||
|
||||
TriggerTutorialSegment(0, GameMain.Config.KeyBindText(InputType.Select), GameMain.Config.KeyBindText(InputType.Deselect), GameMain.Config.KeyBindText(InputType.ToggleInventory)); // Medical supplies objective
|
||||
TriggerTutorialSegment(0, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Select), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Deselect), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.ToggleInventory)); // Medical supplies objective
|
||||
|
||||
do
|
||||
{
|
||||
@@ -215,24 +267,24 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
}
|
||||
yield return null;
|
||||
} while (doctor.Inventory.FindItemByIdentifier("antidama1") == null); // Wait until looted
|
||||
} while (doctor.Inventory.FindItemByIdentifier("antidama1".ToIdentifier()) == null); // Wait until looted
|
||||
yield return new WaitForSeconds(1.0f, false);
|
||||
|
||||
SetHighlight(doctor_suppliesCabinet.Item, false);
|
||||
RemoveCompletedObjective(segments[0]);
|
||||
RemoveCompletedObjective(0);
|
||||
|
||||
yield return new WaitForSeconds(1.0f, false);
|
||||
|
||||
// 2nd tutorial segment, treat self -------------------------------------------------------------------------
|
||||
|
||||
TriggerTutorialSegment(1, GameMain.Config.KeyBindText(InputType.Health)); // Open health interface
|
||||
TriggerTutorialSegment(1, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Health)); // Open health interface
|
||||
while (CharacterHealth.OpenHealthWindow == null)
|
||||
{
|
||||
doctor.CharacterHealth.HealthBarPulsateTimer = 1.0f;
|
||||
yield return null;
|
||||
}
|
||||
yield return null;
|
||||
RemoveCompletedObjective(segments[1]);
|
||||
RemoveCompletedObjective(1);
|
||||
yield return new WaitForSeconds(1.0f, false);
|
||||
TriggerTutorialSegment(2); //Treat self
|
||||
while (doctor.CharacterHealth.GetAfflictionStrength("damage") > 0.01f)
|
||||
@@ -243,13 +295,13 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
else
|
||||
{
|
||||
HighlightInventorySlot(doctor.Inventory, "antidama1", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(doctor.Inventory, "antidama1".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
}
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
RemoveCompletedObjective(segments[2]);
|
||||
RemoveCompletedObjective(2);
|
||||
SetDoorAccess(doctor_firstDoor, doctor_firstDoorLight, true);
|
||||
|
||||
while (CharacterHealth.OpenHealthWindow != null)
|
||||
@@ -260,10 +312,10 @@ namespace Barotrauma.Tutorials
|
||||
// treat patient --------------------------------------------------------------------------------------------
|
||||
|
||||
//patient 1 requests first aid
|
||||
var newOrder = new Order(Order.GetPrefab("requestfirstaid"), patient1.CurrentHull, null, orderGiver: patient1);
|
||||
var newOrder = new Order(OrderPrefab.Prefabs["requestfirstaid"], patient1.CurrentHull, null, orderGiver: patient1);
|
||||
doctor.AddActiveObjectiveEntity(patient1, doctor_firstAidIcon, doctor_firstAidIconColor);
|
||||
//GameMain.GameSession.CrewManager.AddOrder(newOrder, newOrder.FadeOutTime);
|
||||
GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(patient1.Name, newOrder.GetChatMessage("", patient1.CurrentHull?.DisplayName, givingOrderToSelf: false), ChatMessageType.Order, null);
|
||||
GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(patient1.Name, newOrder.GetChatMessage("", patient1.CurrentHull?.DisplayName?.Value, givingOrderToSelf: false), ChatMessageType.Order, null);
|
||||
|
||||
while (doctor.CurrentHull != patient1.CurrentHull)
|
||||
{
|
||||
@@ -281,9 +333,9 @@ namespace Barotrauma.Tutorials
|
||||
yield return new WaitForSeconds(3.0f, false);
|
||||
patient1.AIController.Enabled = true;
|
||||
doctor.RemoveActiveObjectiveEntity(patient1);
|
||||
TriggerTutorialSegment(3, GameMain.Config.KeyBindText(InputType.Command)); // Get the patient to medbay
|
||||
TriggerTutorialSegment(3, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Command)); // Get the patient to medbay
|
||||
|
||||
while (patient1.GetCurrentOrderWithTopPriority()?.Order?.Identifier != "follow")
|
||||
while (patient1.GetCurrentOrderWithTopPriority()?.Identifier != "follow")
|
||||
{
|
||||
// TODO: Rework order highlighting for new command UI
|
||||
// GameMain.GameSession.CrewManager.HighlightOrderButton(patient1, "follow", highlightColor, new Vector2(5, 5));
|
||||
@@ -296,14 +348,14 @@ namespace Barotrauma.Tutorials
|
||||
{
|
||||
yield return new WaitForSeconds(1.0f, false);
|
||||
}
|
||||
RemoveCompletedObjective(segments[3]);
|
||||
RemoveCompletedObjective(3);
|
||||
SetHighlight(doctor_medBayCabinet.Item, true);
|
||||
SetDoorAccess(doctor_thirdDoor, doctor_thirdDoorLight, true);
|
||||
patient1.CharacterHealth.UseHealthWindow = true;
|
||||
|
||||
yield return new WaitForSeconds(2.0f, false);
|
||||
|
||||
TriggerTutorialSegment(4, GameMain.Config.KeyBindText(InputType.Health)); // treat burns
|
||||
TriggerTutorialSegment(4, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Health)); // treat burns
|
||||
|
||||
do
|
||||
{
|
||||
@@ -322,7 +374,7 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
}
|
||||
yield return null;
|
||||
} while (doctor.Inventory.FindItemByIdentifier("antibleeding1") == null); // Wait until looted
|
||||
} while (doctor.Inventory.FindItemByIdentifier("antibleeding1".ToIdentifier()) == null); // Wait until looted
|
||||
SetHighlight(doctor_medBayCabinet.Item, false);
|
||||
SetHighlight(patient1, true);
|
||||
|
||||
@@ -334,12 +386,12 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
else
|
||||
{
|
||||
HighlightInventorySlot(doctor.Inventory, "antibleeding1", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(doctor.Inventory, "antibleeding1".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
}
|
||||
yield return null;
|
||||
|
||||
}
|
||||
RemoveCompletedObjective(segments[4]);
|
||||
RemoveCompletedObjective(4);
|
||||
SetHighlight(patient1, false);
|
||||
yield return new WaitForSeconds(1.0f, false);
|
||||
|
||||
@@ -350,10 +402,10 @@ namespace Barotrauma.Tutorials
|
||||
//patient calls for help
|
||||
//patient2.CanSpeak = true;
|
||||
yield return new WaitForSeconds(2.0f, false);
|
||||
newOrder = new Order(Order.GetPrefab("requestfirstaid"), patient2.CurrentHull, null, orderGiver: patient2);
|
||||
newOrder = new Order(OrderPrefab.Prefabs["requestfirstaid"], patient2.CurrentHull, null, orderGiver: patient2);
|
||||
doctor.AddActiveObjectiveEntity(patient2, doctor_firstAidIcon, doctor_firstAidIconColor);
|
||||
//GameMain.GameSession.CrewManager.AddOrder(newOrder, newOrder.FadeOutTime);
|
||||
GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(patient2.Name, newOrder.GetChatMessage("", patient1.CurrentHull?.DisplayName, givingOrderToSelf: false), ChatMessageType.Order, null);
|
||||
GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(patient2.Name, newOrder.GetChatMessage("", patient1.CurrentHull?.DisplayName?.Value, givingOrderToSelf: false), ChatMessageType.Order, null);
|
||||
patient2.AIController.Enabled = true;
|
||||
patient2.Oxygen = -50;
|
||||
CoroutineManager.StartCoroutine(KeepPatientAlive(patient2), "KeepPatient2Alive");
|
||||
@@ -365,7 +417,7 @@ namespace Barotrauma.Tutorials
|
||||
do { yield return null; } while (!tutorial_upperFinalDoor.IsOpen);
|
||||
yield return new WaitForSeconds(2.0f, false);
|
||||
|
||||
TriggerTutorialSegment(5, GameMain.Config.KeyBindText(InputType.Health)); // perform CPR
|
||||
TriggerTutorialSegment(5, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Health)); // perform CPR
|
||||
SetHighlight(patient2, true);
|
||||
while (patient2.IsUnconscious)
|
||||
{
|
||||
@@ -380,7 +432,7 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
yield return null;
|
||||
}
|
||||
RemoveCompletedObjective(segments[5]);
|
||||
RemoveCompletedObjective(5);
|
||||
SetHighlight(patient2, false);
|
||||
doctor.RemoveActiveObjectiveEntity(patient2);
|
||||
CoroutineManager.StopCoroutines("KeepPatient2Alive");
|
||||
@@ -399,7 +451,7 @@ namespace Barotrauma.Tutorials
|
||||
GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Doctor.Radio.EnteredSub"), ChatMessageType.Radio, null);
|
||||
|
||||
yield return new WaitForSeconds(3.0f, false);
|
||||
TriggerTutorialSegment(6, GameMain.Config.KeyBindText(InputType.Health)); // give treatment to anyone in need
|
||||
TriggerTutorialSegment(6, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Health)); // give treatment to anyone in need
|
||||
|
||||
foreach (var patient in subPatients)
|
||||
{
|
||||
@@ -421,8 +473,8 @@ namespace Barotrauma.Tutorials
|
||||
if (!patientCalledHelp[i] && Timing.TotalTime > subEnterTime + 60 * (i + 1))
|
||||
{
|
||||
doctor.AddActiveObjectiveEntity(subPatients[i], doctor_firstAidIcon, doctor_firstAidIconColor);
|
||||
newOrder = new Order(Order.GetPrefab("requestfirstaid"), subPatients[i].CurrentHull, null, orderGiver: subPatients[i]);
|
||||
string message = newOrder.GetChatMessage("", subPatients[i].CurrentHull?.DisplayName, givingOrderToSelf: false);
|
||||
newOrder = new Order(OrderPrefab.Prefabs["requestfirstaid"], subPatients[i].CurrentHull, null, orderGiver: subPatients[i]);
|
||||
string message = newOrder.GetChatMessage("", subPatients[i].CurrentHull?.DisplayName?.Value, givingOrderToSelf: false);
|
||||
GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(subPatients[i].Name, message, ChatMessageType.Order, null);
|
||||
patientCalledHelp[i] = true;
|
||||
}
|
||||
@@ -435,7 +487,7 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
yield return new WaitForSeconds(1.0f, false);
|
||||
}
|
||||
RemoveCompletedObjective(segments[6]);
|
||||
RemoveCompletedObjective(6);
|
||||
foreach (var patient in subPatients)
|
||||
{
|
||||
SetHighlight(patient, false);
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Tutorials
|
||||
{
|
||||
class EditorTutorial : Tutorial
|
||||
{
|
||||
public EditorTutorial(XElement element)
|
||||
: base (element)
|
||||
{
|
||||
}
|
||||
|
||||
public override IEnumerable<CoroutineStatus> UpdateState()
|
||||
{
|
||||
/*infoBox = CreateInfoFrame("Use the mouse wheel to zoom in and out, and WASD to move the camera around.", true);
|
||||
|
||||
while (infoBox != null)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("Press \"Structure\" at the left side of the screen to start placing some walls.");
|
||||
|
||||
while (GameMain.SubEditorScreen.SelectedTab != (int)MapEntityCategory.Structure)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("Select \"topwall\" from the list.", true);
|
||||
|
||||
while (MapEntityPrefab.Selected == null || MapEntityPrefab.Selected.Name != "topwall")
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("You can now create a horizontal wall by clicking and dragging. When you're done, right click to stop creating walls.");*/
|
||||
|
||||
|
||||
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,7 +62,7 @@ namespace Barotrauma.Tutorials
|
||||
private Reactor engineer_submarineReactor;
|
||||
|
||||
// Variables
|
||||
private string radioSpeakerName;
|
||||
private LocalizedString radioSpeakerName;
|
||||
private Character engineer;
|
||||
private int[] reactorLoads = new int[5] { 1500, 3000, 2000, 5000, 3500 };
|
||||
private float reactorLoadChangeTime = 2f;
|
||||
@@ -75,27 +75,74 @@ namespace Barotrauma.Tutorials
|
||||
private Color engineer_reactorIconColor;
|
||||
private bool wiringActive = false;
|
||||
|
||||
public EngineerTutorial(XElement element) : base(element)
|
||||
{
|
||||
public EngineerTutorial() : base("tutorial.engineertraining".ToIdentifier(),
|
||||
new Segment(
|
||||
"Mechanic.Equipment".ToIdentifier(),
|
||||
"Mechanic.EquipmentObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Mechanic.EquipmentText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Engineer.Reactor".ToIdentifier(),
|
||||
"Engineer.ReactorObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Engineer.ReactorText".ToIdentifier(), Width = 700, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_reactor.webm", TextTag = "Engineer.ReactorText".ToIdentifier(), Width = 700, Height = 80 }),
|
||||
new Segment(
|
||||
"Engineer.OperateReactor".ToIdentifier(),
|
||||
"Engineer.OperateReactorObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Engineer.OperateReactorText".ToIdentifier(), Width = 700, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_reactor.webm", TextTag = "Engineer.ReactorText".ToIdentifier(), Width = 700, Height = 80 }),
|
||||
new Segment(
|
||||
"Engineer.RepairJunctionBox".ToIdentifier(),
|
||||
"Engineer.RepairJunctionBoxObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Engineer.RepairJunctionBoxText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Engineer.WireJunctionBoxes".ToIdentifier(),
|
||||
"Engineer.WireJunctionBoxesObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Engineer.WireJunctionBoxesText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_wiring.webm", TextTag = "Engineer.WireJunctionBoxesText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Engineer.RepairElectricalRoom".ToIdentifier(),
|
||||
"Engineer.RepairElectricalRoomObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Engineer.RepairElectricalRoomText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Engineer.PowerUpReactor".ToIdentifier(),
|
||||
"Engineer.PowerUpReactorObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Engineer.PowerUpReactorText".ToIdentifier(), Width = 700, Height = 80, Anchor = Anchor.Center }))
|
||||
{ }
|
||||
|
||||
protected override CharacterInfo GetCharacterInfo()
|
||||
{
|
||||
return new CharacterInfo(
|
||||
CharacterPrefab.HumanSpeciesName,
|
||||
jobOrJobPrefab: new Job(
|
||||
JobPrefab.Prefabs["engineer"], Rand.RandSync.Unsynced, 0,
|
||||
new Skill("medical".ToIdentifier(), 0),
|
||||
new Skill("weapons".ToIdentifier(), 0),
|
||||
new Skill("mechanical".ToIdentifier(), 20),
|
||||
new Skill("electrical".ToIdentifier(), 60),
|
||||
new Skill("helm".ToIdentifier(), 0)));
|
||||
}
|
||||
|
||||
public override void Start()
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
radioSpeakerName = TextManager.Get("Tutorial.Radio.Speaker");
|
||||
engineer = Character.Controlled;
|
||||
|
||||
var toolbelt = FindOrGiveItem(engineer, "toolbelt");
|
||||
var toolbelt = FindOrGiveItem(engineer, "toolbelt".ToIdentifier());
|
||||
toolbelt.Unequip(engineer);
|
||||
engineer.Inventory.RemoveItem(toolbelt);
|
||||
|
||||
var repairOrder = Order.GetPrefab("repairsystems");
|
||||
var repairOrder = OrderPrefab.Prefabs["repairsystems"];
|
||||
engineer_repairIcon = repairOrder.SymbolSprite;
|
||||
engineer_repairIconColor = repairOrder.Color;
|
||||
|
||||
var reactorOrder = Order.GetPrefab("operatereactor");
|
||||
var reactorOrder = OrderPrefab.Prefabs["operatereactor"];
|
||||
engineer_reactorIcon = reactorOrder.SymbolSprite;
|
||||
engineer_reactorIconColor = reactorOrder.Color;
|
||||
|
||||
@@ -235,7 +282,7 @@ namespace Barotrauma.Tutorials
|
||||
do { yield return null; } while (!engineer_equipmentObjectiveSensor.MotionDetected);
|
||||
GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Engineer.Radio.Equipment"), ChatMessageType.Radio, null);
|
||||
yield return new WaitForSeconds(0.5f, false);
|
||||
TriggerTutorialSegment(0, GameMain.Config.KeyBindText(InputType.Select), GameMain.Config.KeyBindText(InputType.Deselect), GameMain.Config.KeyBindText(InputType.ToggleInventory)); // Retrieve equipment
|
||||
TriggerTutorialSegment(0, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Select), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Deselect), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.ToggleInventory)); // Retrieve equipment
|
||||
bool firstSlotRemoved = false;
|
||||
bool secondSlotRemoved = false;
|
||||
bool thirdSlotRemoved = false;
|
||||
@@ -276,7 +323,7 @@ namespace Barotrauma.Tutorials
|
||||
|
||||
yield return null;
|
||||
} while (!engineer_equipmentCabinet.Inventory.IsEmpty()); // Wait until looted
|
||||
RemoveCompletedObjective(segments[0]);
|
||||
RemoveCompletedObjective(0);
|
||||
SetHighlight(engineer_equipmentCabinet.Item, false);
|
||||
SetHighlight(engineer_reactor.Item, true);
|
||||
SetDoorAccess(engineer_firstDoor, engineer_firstDoorLight, true);
|
||||
@@ -302,7 +349,7 @@ namespace Barotrauma.Tutorials
|
||||
if (IsSelectedItem(engineer_reactor.Item) && engineer_reactor.Item.OwnInventory.visualSlots != null)
|
||||
{
|
||||
engineer_reactor.AutoTemp = false;
|
||||
HighlightInventorySlot(engineer.Inventory, "fuelrod", highlightColor, 0.5f, 0.5f, 0f);
|
||||
HighlightInventorySlot(engineer.Inventory, "fuelrod".ToIdentifier(), highlightColor, 0.5f, 0.5f, 0f);
|
||||
|
||||
for (int i = 0; i < engineer_reactor.Item.OwnInventory.visualSlots.Length; i++)
|
||||
{
|
||||
@@ -311,7 +358,7 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
yield return null;
|
||||
} while (engineer_reactor.AvailableFuel == 0);
|
||||
RemoveCompletedObjective(segments[1]);
|
||||
RemoveCompletedObjective(1);
|
||||
TriggerTutorialSegment(2);
|
||||
CoroutineManager.StartCoroutine(ReactorOperatedProperly());
|
||||
do
|
||||
@@ -354,7 +401,7 @@ namespace Barotrauma.Tutorials
|
||||
} while (wait > 0.0f);
|
||||
engineer.SelectedConstruction = null;
|
||||
engineer_reactor.CanBeSelected = false;
|
||||
RemoveCompletedObjective(segments[2]);
|
||||
RemoveCompletedObjective(2);
|
||||
SetHighlight(engineer_reactor.Item, false);
|
||||
SetHighlight(engineer_brokenJunctionBox, true);
|
||||
SetDoorAccess(engineer_secondDoor, engineer_secondDoorLight, true);
|
||||
@@ -363,12 +410,12 @@ namespace Barotrauma.Tutorials
|
||||
do { yield return null; } while (!engineer_secondDoor.IsOpen);
|
||||
yield return new WaitForSeconds(1f, false);
|
||||
Repairable repairableJunctionBoxComponent = engineer_brokenJunctionBox.GetComponent<Repairable>();
|
||||
TriggerTutorialSegment(3, GameMain.Config.KeyBindText(InputType.Select)); // Repair the junction box
|
||||
TriggerTutorialSegment(3, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Select)); // Repair the junction box
|
||||
do
|
||||
{
|
||||
if (!engineer.HasEquippedItem("screwdriver"))
|
||||
if (!engineer.HasEquippedItem("screwdriver".ToIdentifier()))
|
||||
{
|
||||
HighlightInventorySlot(engineer.Inventory, "screwdriver", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(engineer.Inventory, "screwdriver".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
}
|
||||
else if (IsSelectedItem(engineer_brokenJunctionBox) && repairableJunctionBoxComponent.CurrentFixer == null)
|
||||
{
|
||||
@@ -380,7 +427,7 @@ namespace Barotrauma.Tutorials
|
||||
yield return null;
|
||||
} while (repairableJunctionBoxComponent.IsBelowRepairThreshold); // Wait until repaired
|
||||
SetHighlight(engineer_brokenJunctionBox, false);
|
||||
RemoveCompletedObjective(segments[3]);
|
||||
RemoveCompletedObjective(3);
|
||||
SetDoorAccess(engineer_thirdDoor, engineer_thirdDoorLight, true);
|
||||
for (int i = 0; i < engineer_disconnectedJunctionBoxes.Length; i++)
|
||||
{
|
||||
@@ -391,14 +438,14 @@ namespace Barotrauma.Tutorials
|
||||
do { yield return null; } while (!engineer_thirdDoor.IsOpen);
|
||||
GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Engineer.Radio.FaultyWiring"), ChatMessageType.Radio, null);
|
||||
yield return new WaitForSeconds(2f, false);
|
||||
TriggerTutorialSegment(4, GameMain.Config.KeyBindText(InputType.Use), GameMain.Config.KeyBindText(InputType.Deselect)); // Connect the junction boxes
|
||||
TriggerTutorialSegment(4, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Use), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Deselect)); // Connect the junction boxes
|
||||
do { CheckGhostWires(); HandleJunctionBoxWiringHighlights(); yield return null; } while (engineer_workingPump.Voltage < engineer_workingPump.MinVoltage); // Wait until connected all the way to the pump
|
||||
CheckGhostWires();
|
||||
for (int i = 0; i < engineer_disconnectedJunctionBoxes.Length; i++)
|
||||
{
|
||||
SetHighlight(engineer_disconnectedJunctionBoxes[i].Item, false);
|
||||
}
|
||||
RemoveCompletedObjective(segments[4]);
|
||||
RemoveCompletedObjective(4);
|
||||
do { yield return null; } while (engineer_workingPump.Item.CurrentHull.WaterPercentage > waterVolumeBeforeOpening); // Wait until drained
|
||||
wiringActive = false;
|
||||
SetDoorAccess(engineer_fourthDoor, engineer_fourthDoorLight, true);
|
||||
@@ -424,7 +471,7 @@ namespace Barotrauma.Tutorials
|
||||
// Remove highlights when each individual machine is repaired
|
||||
do { CheckJunctionBoxHighlights(repairableJunctionBoxComponent1, repairableJunctionBoxComponent2, repairableJunctionBoxComponent3); yield return null; } while (repairableJunctionBoxComponent1.IsBelowRepairThreshold || repairableJunctionBoxComponent2.IsBelowRepairThreshold || repairableJunctionBoxComponent3.IsBelowRepairThreshold);
|
||||
CheckJunctionBoxHighlights(repairableJunctionBoxComponent1, repairableJunctionBoxComponent2, repairableJunctionBoxComponent3);
|
||||
RemoveCompletedObjective(segments[5]);
|
||||
RemoveCompletedObjective(5);
|
||||
yield return new WaitForSeconds(2f, false);
|
||||
|
||||
TriggerTutorialSegment(6); // Powerup reactor
|
||||
@@ -433,7 +480,7 @@ namespace Barotrauma.Tutorials
|
||||
do { yield return null; } while (!IsReactorPoweredUp(engineer_submarineReactor)); // Wait until ~matches load
|
||||
engineer.RemoveActiveObjectiveEntity(engineer_submarineReactor.Item);
|
||||
SetHighlight(engineer_submarineReactor.Item, false);
|
||||
RemoveCompletedObjective(segments[6]);
|
||||
RemoveCompletedObjective(6);
|
||||
GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Engineer.Radio.Complete"), ChatMessageType.Radio, null);
|
||||
|
||||
yield return new WaitForSeconds(4f, false);
|
||||
@@ -516,9 +563,9 @@ namespace Barotrauma.Tutorials
|
||||
{
|
||||
Item selected = engineer.SelectedConstruction;
|
||||
|
||||
if (!engineer.HasEquippedItem("screwdriver"))
|
||||
if (!engineer.HasEquippedItem("screwdriver".ToIdentifier()))
|
||||
{
|
||||
HighlightInventorySlot(engineer.Inventory, "screwdriver", highlightColor, 0.5f, 0.5f, 0f);
|
||||
HighlightInventorySlot(engineer.Inventory, "screwdriver".ToIdentifier(), highlightColor, 0.5f, 0.5f, 0f);
|
||||
}
|
||||
|
||||
int selectedIndex = -1;
|
||||
@@ -537,9 +584,9 @@ namespace Barotrauma.Tutorials
|
||||
|
||||
wiringActive = selectedIndex != -1;
|
||||
|
||||
if (!engineer.HasEquippedItem("wire"))
|
||||
if (!engineer.HasEquippedItem("wire".ToIdentifier()))
|
||||
{
|
||||
HighlightInventorySlotWithTag(engineer.Inventory, "wire", highlightColor, 0.5f, 0.5f, 0f);
|
||||
HighlightInventorySlotWithTag(engineer.Inventory, "wire".ToIdentifier(), highlightColor, 0.5f, 0.5f, 0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -69,33 +69,106 @@ namespace Barotrauma.Tutorials
|
||||
|
||||
// Variables
|
||||
private const float waterVolumeBeforeOpening = 15f;
|
||||
private string radioSpeakerName;
|
||||
private LocalizedString radioSpeakerName;
|
||||
private Character mechanic;
|
||||
private Sprite mechanic_repairIcon;
|
||||
private Color mechanic_repairIconColor;
|
||||
private Sprite mechanic_weldIcon;
|
||||
|
||||
public MechanicTutorial(XElement element) : base(element)
|
||||
{
|
||||
public MechanicTutorial() : base("tutorial.mechanictraining".ToIdentifier(),
|
||||
new Segment(
|
||||
"Mechanic.OpenDoor".ToIdentifier(),
|
||||
"Mechanic.OpenDoorObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Mechanic.OpenDoorText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Mechanic.Equipment".ToIdentifier(),
|
||||
"Mechanic.EquipmentObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Mechanic.EquipmentText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_inventory.webm", TextTag = "Mechanic.EquipmentText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Mechanic.Welding".ToIdentifier(),
|
||||
"Mechanic.WeldingObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Mechanic.WeldingText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_equip.webm", TextTag = "Mechanic.WeldingText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Mechanic.Drain".ToIdentifier(),
|
||||
"Mechanic.DrainObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Mechanic.DrainText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Mechanic.Deconstruct".ToIdentifier(),
|
||||
"Mechanic.DeconstructObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Mechanic.DeconstructText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_deconstruct.webm", TextTag = "Mechanic.DeconstructText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Mechanic.Fabricate".ToIdentifier(),
|
||||
"Mechanic.FabricateObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Mechanic.FabricateText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_fabricate.webm", TextTag = "Mechanic.FabricateText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Mechanic.Extinguisher".ToIdentifier(),
|
||||
"Mechanic.ExtinguisherObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Mechanic.ExtinguisherText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Mechanic.DropExtinguisher".ToIdentifier(),
|
||||
"Mechanic.DropExtinguisherObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Mechanic.DropExtinguisherText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Mechanic.Diving".ToIdentifier(),
|
||||
"Mechanic.DivingObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Mechanic.DivingText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Mechanic.RepairPump".ToIdentifier(),
|
||||
"Mechanic.RepairPumpObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Mechanic.RepairPumpText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Mechanic.RepairSubmarine".ToIdentifier(),
|
||||
"Mechanic.RepairSubmarineObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Mechanic.RepairSubmarineText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"tutorial.laddertitle".ToIdentifier(),
|
||||
"tutorial.laddertitle".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "tutorial.ladderdescription".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }))
|
||||
{ }
|
||||
|
||||
protected override CharacterInfo GetCharacterInfo()
|
||||
{
|
||||
return new CharacterInfo(
|
||||
CharacterPrefab.HumanSpeciesName,
|
||||
jobOrJobPrefab: new Job(
|
||||
JobPrefab.Prefabs["mechanic"], Rand.RandSync.Unsynced, 0,
|
||||
new Skill("medical".ToIdentifier(), 0),
|
||||
new Skill("weapons".ToIdentifier(), 0),
|
||||
new Skill("mechanical".ToIdentifier(), 50),
|
||||
new Skill("electrical".ToIdentifier(), 20),
|
||||
new Skill("helm".ToIdentifier(), 0)));
|
||||
}
|
||||
|
||||
public override void Start()
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
radioSpeakerName = TextManager.Get("Tutorial.Radio.Speaker");
|
||||
mechanic = Character.Controlled;
|
||||
|
||||
var toolbelt = FindOrGiveItem(mechanic, "toolbelt");
|
||||
var toolbelt = FindOrGiveItem(mechanic, "toolbelt".ToIdentifier());
|
||||
toolbelt.Unequip(mechanic);
|
||||
mechanic.Inventory.RemoveItem(toolbelt);
|
||||
|
||||
var crowbar = FindOrGiveItem(mechanic, "crowbar");
|
||||
var crowbar = FindOrGiveItem(mechanic, "crowbar".ToIdentifier());
|
||||
crowbar.Unequip(mechanic);
|
||||
mechanic.Inventory.RemoveItem(crowbar);
|
||||
|
||||
var repairOrder = Order.GetPrefab("repairsystems");
|
||||
var repairOrder = OrderPrefab.Prefabs["repairsystems"];
|
||||
mechanic_repairIcon = repairOrder.SymbolSprite;
|
||||
mechanic_repairIconColor = repairOrder.Color;
|
||||
mechanic_weldIcon = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(1, 256, 127, 127), new Vector2(0.5f, 0.5f));
|
||||
@@ -239,24 +312,25 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
yield return new WaitForSeconds(2.5f, false);
|
||||
|
||||
mechanic_fabricator.RemoveFabricationRecipes(new List<string>() { "extinguisher", "wrench", "weldingtool", "weldingfuel", "divingmask", "railgunshell", "nuclearshell", "uex", "harpoongun" });
|
||||
mechanic_fabricator.RemoveFabricationRecipes(allowedIdentifiers:
|
||||
new[] { "extinguisher", "wrench", "weldingtool", "weldingfuel", "divingmask", "railgunshell", "nuclearshell", "uex", "harpoongun" }.ToIdentifiers());
|
||||
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.WakeUp"), ChatMessageType.Radio, null);
|
||||
|
||||
yield return new WaitForSeconds(2.5f, false);
|
||||
TriggerTutorialSegment(0, GameMain.Config.KeyBindText(InputType.Up), GameMain.Config.KeyBindText(InputType.Left), GameMain.Config.KeyBindText(InputType.Down), GameMain.Config.KeyBindText(InputType.Right), GameMain.Config.KeyBindText(InputType.Select), GameMain.Config.KeyBindText(InputType.Select)); // Open door objective
|
||||
TriggerTutorialSegment(0, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Up), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Left), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Down), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Right), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Select), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Select)); // Open door objective
|
||||
yield return new WaitForSeconds(0.0f, false);
|
||||
SetDoorAccess(mechanic_firstDoor, mechanic_firstDoorLight, true);
|
||||
SetHighlight(mechanic_firstDoor.Item, true);
|
||||
do { yield return null; } while (!mechanic_firstDoor.IsOpen);
|
||||
SetHighlight(mechanic_firstDoor.Item, false);
|
||||
yield return new WaitForSeconds(1.5f, false);
|
||||
RemoveCompletedObjective(segments[0]);
|
||||
RemoveCompletedObjective(0);
|
||||
|
||||
// Room 2
|
||||
yield return new WaitForSeconds(0.0f, false);
|
||||
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.Equipment"), ChatMessageType.Radio, null);
|
||||
do { yield return null; } while (!mechanic_equipmentObjectiveSensor.MotionDetected);
|
||||
TriggerTutorialSegment(1, GameMain.Config.KeyBindText(InputType.Select), GameMain.Config.KeyBindText(InputType.Deselect), GameMain.Config.KeyBindText(InputType.ToggleInventory)); // Equipment & inventory objective
|
||||
TriggerTutorialSegment(1, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Select), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Deselect), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.ToggleInventory)); // Equipment & inventory objective
|
||||
SetHighlight(mechanic_equipmentCabinet.Item, true);
|
||||
bool firstSlotRemoved = false;
|
||||
bool secondSlotRemoved = false;
|
||||
@@ -290,35 +364,35 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
|
||||
yield return null;
|
||||
} while (mechanic.Inventory.FindItemByIdentifier("divingmask") == null || mechanic.Inventory.FindItemByIdentifier("weldingtool") == null || mechanic.Inventory.FindItemByIdentifier("wrench") == null); // Wait until looted
|
||||
} while (mechanic.Inventory.FindItemByIdentifier("divingmask".ToIdentifier()) == null || mechanic.Inventory.FindItemByIdentifier("weldingtool".ToIdentifier()) == null || mechanic.Inventory.FindItemByIdentifier("wrench".ToIdentifier()) == null); // Wait until looted
|
||||
SetHighlight(mechanic_equipmentCabinet.Item, false);
|
||||
yield return new WaitForSeconds(1.5f, false);
|
||||
RemoveCompletedObjective(segments[1]);
|
||||
RemoveCompletedObjective(1);
|
||||
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.Breach"), ChatMessageType.Radio, null);
|
||||
|
||||
// Room 3
|
||||
do { yield return null; } while (!mechanic_weldingObjectiveSensor.MotionDetected);
|
||||
TriggerTutorialSegment(2, GameMain.Config.KeyBindText(InputType.Aim), GameMain.Config.KeyBindText(InputType.Shoot), GameMain.Config.KeyBindText(InputType.ToggleInventory)); // Welding objective
|
||||
TriggerTutorialSegment(2, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Aim), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Shoot), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.ToggleInventory)); // Welding objective
|
||||
do
|
||||
{
|
||||
if (!mechanic.HasEquippedItem("divingmask"))
|
||||
if (!mechanic.HasEquippedItem("divingmask".ToIdentifier()))
|
||||
{
|
||||
HighlightInventorySlot(mechanic.Inventory, "divingmask", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(mechanic.Inventory, "divingmask".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
}
|
||||
|
||||
if (!mechanic.HasEquippedItem("weldingtool"))
|
||||
if (!mechanic.HasEquippedItem("weldingtool".ToIdentifier()))
|
||||
{
|
||||
HighlightInventorySlot(mechanic.Inventory, "weldingtool", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(mechanic.Inventory, "weldingtool".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
}
|
||||
yield return null;
|
||||
} while (!mechanic.HasEquippedItem("divingmask") || !mechanic.HasEquippedItem("weldingtool")); // Wait until equipped
|
||||
} while (!mechanic.HasEquippedItem("divingmask".ToIdentifier()) || !mechanic.HasEquippedItem("weldingtool".ToIdentifier())); // Wait until equipped
|
||||
SetDoorAccess(mechanic_secondDoor, mechanic_secondDoorLight, true);
|
||||
mechanic.AddActiveObjectiveEntity(mechanic_brokenWall_1, mechanic_weldIcon, mechanic_repairIconColor);
|
||||
do { yield return null; } while (WallHasDamagedSections(mechanic_brokenWall_1)); // Highlight until repaired
|
||||
mechanic.RemoveActiveObjectiveEntity(mechanic_brokenWall_1);
|
||||
RemoveCompletedObjective(segments[2]);
|
||||
RemoveCompletedObjective(2);
|
||||
yield return new WaitForSeconds(1f, false);
|
||||
TriggerTutorialSegment(3, GameMain.Config.KeyBindText(InputType.Select)); // Pump objective
|
||||
TriggerTutorialSegment(3, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Select)); // Pump objective
|
||||
SetHighlight(mechanic_workingPump.Item, true);
|
||||
do
|
||||
{
|
||||
@@ -333,9 +407,9 @@ namespace Barotrauma.Tutorials
|
||||
} while (mechanic_workingPump.FlowPercentage >= 0 || !mechanic_workingPump.IsActive); // Highlight until draining
|
||||
SetHighlight(mechanic_workingPump.Item, false);
|
||||
do { yield return null; } while (mechanic_brokenhull_1.WaterPercentage > waterVolumeBeforeOpening); // Unlock door once drained
|
||||
RemoveCompletedObjective(segments[3]);
|
||||
RemoveCompletedObjective(3);
|
||||
SetDoorAccess(mechanic_thirdDoor, mechanic_thirdDoorLight, true);
|
||||
//TriggerTutorialSegment(11, GameMain.Config.KeyBind(InputType.Select), GameMain.Config.KeyBind(InputType.Up), GameMain.Config.KeyBind(InputType.Down), GameMain.Config.KeyBind(InputType.Select)); // Ladder objective
|
||||
//TriggerTutorialSegment(11, GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Select], GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Up], GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Down], GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Select]); // Ladder objective
|
||||
//do { yield return null; } while (!mechanic_ladderSensor.MotionDetected);
|
||||
//RemoveCompletedObjective(segments[11]);
|
||||
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.News"), ChatMessageType.Radio, null);
|
||||
@@ -362,24 +436,24 @@ namespace Barotrauma.Tutorials
|
||||
if (mechanic.Inventory.GetItemAt(i) == null) { HighlightInventorySlot(mechanic.Inventory, i, highlightColor, .5f, .5f, 0f); }
|
||||
}
|
||||
|
||||
if (mechanic.Inventory.FindItemByIdentifier("oxygentank") == null && mechanic.Inventory.FindItemByIdentifier("aluminium") == null)
|
||||
if (mechanic.Inventory.FindItemByIdentifier("oxygentank".ToIdentifier()) == null && mechanic.Inventory.FindItemByIdentifier("aluminium".ToIdentifier()) == null)
|
||||
{
|
||||
for (int i = 0; i < mechanic_craftingCabinet.Capacity; i++)
|
||||
{
|
||||
Item item = mechanic_craftingCabinet.Inventory.GetItemAt(i);
|
||||
if (item != null && item.prefab.Identifier == "oxygentank")
|
||||
if (item != null && item.Prefab.Identifier == "oxygentank")
|
||||
{
|
||||
HighlightInventorySlot(mechanic_craftingCabinet.Inventory, i, highlightColor, .5f, .5f, 0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mechanic.Inventory.FindItemByIdentifier("sodium") == null)
|
||||
if (mechanic.Inventory.FindItemByIdentifier("sodium".ToIdentifier()) == null)
|
||||
{
|
||||
for (int i = 0; i < mechanic_craftingCabinet.Inventory.Capacity; i++)
|
||||
{
|
||||
Item item = mechanic_craftingCabinet.Inventory.GetItemAt(i);
|
||||
if (item != null && item.prefab.Identifier == "sodium")
|
||||
if (item != null && item.Prefab.Identifier == "sodium")
|
||||
{
|
||||
HighlightInventorySlot(mechanic_craftingCabinet.Inventory, i, highlightColor, .5f, .5f, 0f);
|
||||
}
|
||||
@@ -387,12 +461,12 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
}
|
||||
|
||||
if (!gotOxygenTank && (mechanic.Inventory.FindItemByIdentifier("oxygentank") != null ||
|
||||
mechanic_deconstructor.InputContainer.Inventory.FindItemByIdentifier("oxygentank") != null))
|
||||
if (!gotOxygenTank && (mechanic.Inventory.FindItemByIdentifier("oxygentank".ToIdentifier()) != null ||
|
||||
mechanic_deconstructor.InputContainer.Inventory.FindItemByIdentifier("oxygentank".ToIdentifier()) != null))
|
||||
{
|
||||
gotOxygenTank = true;
|
||||
}
|
||||
if (!gotSodium && mechanic.Inventory.FindItemByIdentifier("sodium") != null)
|
||||
if (!gotSodium && mechanic.Inventory.FindItemByIdentifier("sodium".ToIdentifier()) != null)
|
||||
{
|
||||
gotSodium = true;
|
||||
}
|
||||
@@ -406,9 +480,9 @@ namespace Barotrauma.Tutorials
|
||||
{
|
||||
if (IsSelectedItem(mechanic_deconstructor.Item))
|
||||
{
|
||||
if (mechanic_deconstructor.OutputContainer.Inventory.FindItemByIdentifier("aluminium") != null)
|
||||
if (mechanic_deconstructor.OutputContainer.Inventory.FindItemByIdentifier("aluminium".ToIdentifier()) != null)
|
||||
{
|
||||
HighlightInventorySlot(mechanic_deconstructor.OutputContainer.Inventory, "aluminium", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(mechanic_deconstructor.OutputContainer.Inventory, "aluminium".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
|
||||
for (int i = 0; i < mechanic.Inventory.Capacity; i++)
|
||||
{
|
||||
@@ -417,16 +491,16 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mechanic.Inventory.FindItemByIdentifier("oxygentank") != null && mechanic_deconstructor.InputContainer.Inventory.FindItemByIdentifier("oxygentank") == null)
|
||||
if (mechanic.Inventory.FindItemByIdentifier("oxygentank".ToIdentifier()) != null && mechanic_deconstructor.InputContainer.Inventory.FindItemByIdentifier("oxygentank".ToIdentifier()) == null)
|
||||
{
|
||||
HighlightInventorySlot(mechanic.Inventory, "oxygentank", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(mechanic.Inventory, "oxygentank".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
for (int i = 0; i < mechanic_deconstructor.InputContainer.Inventory.Capacity; i++)
|
||||
{
|
||||
HighlightInventorySlot(mechanic_deconstructor.InputContainer.Inventory, i, highlightColor, .5f, .5f, 0f);
|
||||
}
|
||||
}
|
||||
|
||||
if (mechanic_deconstructor.InputContainer.Inventory.FindItemByIdentifier("oxygentank") != null && !mechanic_deconstructor.IsActive)
|
||||
if (mechanic_deconstructor.InputContainer.Inventory.FindItemByIdentifier("oxygentank".ToIdentifier()) != null && !mechanic_deconstructor.IsActive)
|
||||
{
|
||||
if (mechanic_deconstructor.ActivateButton.FlashTimer <= 0)
|
||||
{
|
||||
@@ -437,11 +511,11 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
yield return null;
|
||||
} while (
|
||||
mechanic.Inventory.FindItemByIdentifier("aluminium") == null &&
|
||||
mechanic_fabricator.InputContainer.Inventory.FindItemByIdentifier("aluminium") == null); // Wait until aluminium obtained
|
||||
mechanic.Inventory.FindItemByIdentifier("aluminium".ToIdentifier()) == null &&
|
||||
mechanic_fabricator.InputContainer.Inventory.FindItemByIdentifier("aluminium".ToIdentifier()) == null); // Wait until aluminium obtained
|
||||
|
||||
SetHighlight(mechanic_deconstructor.Item, false);
|
||||
RemoveCompletedObjective(segments[4]);
|
||||
SetHighlight(mechanic_deconstructor.Item, false);
|
||||
RemoveCompletedObjective(4);
|
||||
yield return new WaitForSeconds(1f, false);
|
||||
TriggerTutorialSegment(5); // Fabricate
|
||||
SetHighlight(mechanic_fabricator.Item, true);
|
||||
@@ -455,26 +529,26 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mechanic_fabricator.OutputContainer.Inventory.FindItemByIdentifier("extinguisher") != null)
|
||||
if (mechanic_fabricator.OutputContainer.Inventory.FindItemByIdentifier("extinguisher".ToIdentifier()) != null)
|
||||
{
|
||||
HighlightInventorySlot(mechanic_fabricator.OutputContainer.Inventory, "extinguisher", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(mechanic_fabricator.OutputContainer.Inventory, "extinguisher".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
|
||||
/*for (int i = 0; i < mechanic.Inventory.Capacity; i++)
|
||||
{
|
||||
if (mechanic.Inventory.Items[i] == null) HighlightInventorySlot(mechanic.Inventory, i, highlightColor, .5f, .5f, 0f);
|
||||
}*/
|
||||
}
|
||||
else if (mechanic_fabricator.InputContainer.Inventory.FindItemByIdentifier("aluminium") != null && mechanic_fabricator.InputContainer.Inventory.FindItemByIdentifier("sodium") != null && !mechanic_fabricator.IsActive)
|
||||
else if (mechanic_fabricator.InputContainer.Inventory.FindItemByIdentifier("aluminium".ToIdentifier()) != null && mechanic_fabricator.InputContainer.Inventory.FindItemByIdentifier("sodium".ToIdentifier()) != null && !mechanic_fabricator.IsActive)
|
||||
{
|
||||
if (mechanic_fabricator.ActivateButton.FlashTimer <= 0)
|
||||
{
|
||||
mechanic_fabricator.ActivateButton.Flash(highlightColor, 1.5f, false);
|
||||
}
|
||||
}
|
||||
else if (mechanic.Inventory.FindItemByIdentifier("aluminium") != null || mechanic.Inventory.FindItemByIdentifier("sodium") != null)
|
||||
else if (mechanic.Inventory.FindItemByIdentifier("aluminium".ToIdentifier()) != null || mechanic.Inventory.FindItemByIdentifier("sodium".ToIdentifier()) != null)
|
||||
{
|
||||
HighlightInventorySlot(mechanic.Inventory, "aluminium", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(mechanic.Inventory, "sodium", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(mechanic.Inventory, "aluminium".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(mechanic.Inventory, "sodium".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
|
||||
if (mechanic_fabricator.InputContainer.Inventory.GetItemAt(0) == null)
|
||||
{
|
||||
@@ -489,27 +563,27 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
}
|
||||
yield return null;
|
||||
} while (mechanic.Inventory.FindItemByIdentifier("extinguisher") == null); // Wait until extinguisher is created
|
||||
RemoveCompletedObjective(segments[5]);
|
||||
} while (mechanic.Inventory.FindItemByIdentifier("extinguisher".ToIdentifier()) == null); // Wait until extinguisher is created
|
||||
RemoveCompletedObjective(5);
|
||||
SetHighlight(mechanic_fabricator.Item, false);
|
||||
SetDoorAccess(mechanic_fourthDoor, mechanic_fourthDoorLight, true);
|
||||
|
||||
// Room 5
|
||||
do { yield return null; } while (!mechanic_fireSensor.MotionDetected);
|
||||
TriggerTutorialSegment(6, GameMain.Config.KeyBindText(InputType.Aim), GameMain.Config.KeyBindText(InputType.Shoot)); // Using the extinguisher
|
||||
TriggerTutorialSegment(6, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Aim), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Shoot)); // Using the extinguisher
|
||||
do { yield return null; } while (!mechanic_fire.Removed); // Wait until extinguished
|
||||
yield return new WaitForSeconds(3f, false);
|
||||
RemoveCompletedObjective(segments[6]);
|
||||
RemoveCompletedObjective(6);
|
||||
|
||||
if (mechanic.HasEquippedItem("extinguisher")) // do not trigger if dropped already
|
||||
if (mechanic.HasEquippedItem("extinguisher".ToIdentifier())) // do not trigger if dropped already
|
||||
{
|
||||
TriggerTutorialSegment(7);
|
||||
do
|
||||
{
|
||||
HighlightInventorySlot(mechanic.Inventory, "extinguisher", highlightColor, 0.5f, 0.5f, 0f);
|
||||
HighlightInventorySlot(mechanic.Inventory, "extinguisher".ToIdentifier(), highlightColor, 0.5f, 0.5f, 0f);
|
||||
yield return null;
|
||||
} while (mechanic.HasEquippedItem("extinguisher"));
|
||||
RemoveCompletedObjective(segments[7]);
|
||||
} while (mechanic.HasEquippedItem("extinguisher".ToIdentifier()));
|
||||
RemoveCompletedObjective(7);
|
||||
}
|
||||
SetDoorAccess(mechanic_fifthDoor, mechanic_fifthDoorLight, true);
|
||||
|
||||
@@ -531,9 +605,9 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
}
|
||||
yield return null;
|
||||
} while (!mechanic.HasEquippedItem("divingsuit", slotType: InvSlotType.OuterClothes));
|
||||
} while (!mechanic.HasEquippedItem("divingsuit".ToIdentifier(), slotType: InvSlotType.OuterClothes));
|
||||
SetHighlight(mechanic_divingSuitContainer.Item, false);
|
||||
RemoveCompletedObjective(segments[8]);
|
||||
RemoveCompletedObjective(8);
|
||||
SetDoorAccess(tutorial_mechanicFinalDoor, tutorial_mechanicFinalDoorLight, true);
|
||||
|
||||
// Room 7
|
||||
@@ -542,7 +616,7 @@ namespace Barotrauma.Tutorials
|
||||
mechanic.RemoveActiveObjectiveEntity(mechanic_brokenWall_2);
|
||||
yield return new WaitForSeconds(2f, false);
|
||||
|
||||
TriggerTutorialSegment(9, GameMain.Config.KeyBindText(InputType.Use)); // Repairing machinery (pump)
|
||||
TriggerTutorialSegment(9, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Use)); // Repairing machinery (pump)
|
||||
SetHighlight(mechanic_brokenPump.Item, true);
|
||||
mechanic_brokenPump.CanBeSelected = true;
|
||||
Repairable repairablePumpComponent = mechanic_brokenPump.Item.GetComponent<Repairable>();
|
||||
@@ -552,9 +626,9 @@ namespace Barotrauma.Tutorials
|
||||
yield return null;
|
||||
if (repairablePumpComponent.IsBelowRepairThreshold)
|
||||
{
|
||||
if (!mechanic.HasEquippedItem("wrench"))
|
||||
if (!mechanic.HasEquippedItem("wrench".ToIdentifier()))
|
||||
{
|
||||
HighlightInventorySlot(mechanic.Inventory, "wrench", highlightColor, 0.5f, 0.5f, 0f);
|
||||
HighlightInventorySlot(mechanic.Inventory, "wrench".ToIdentifier(), highlightColor, 0.5f, 0.5f, 0f);
|
||||
}
|
||||
else if (IsSelectedItem(mechanic_brokenPump.Item) && repairablePumpComponent.CurrentFixer == null)
|
||||
{
|
||||
@@ -575,7 +649,7 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
}
|
||||
} while (repairablePumpComponent.IsBelowRepairThreshold || mechanic_brokenPump.FlowPercentage >= 0 || !mechanic_brokenPump.IsActive);
|
||||
RemoveCompletedObjective(segments[9]);
|
||||
RemoveCompletedObjective(9);
|
||||
SetHighlight(mechanic_brokenPump.Item, false);
|
||||
do { yield return null; } while (mechanic_brokenhull_2.WaterPercentage > waterVolumeBeforeOpening);
|
||||
SetDoorAccess(tutorial_submarineDoor, tutorial_submarineDoorLight, true);
|
||||
@@ -599,7 +673,7 @@ namespace Barotrauma.Tutorials
|
||||
// Remove highlights when each individual machine is repaired
|
||||
do { CheckHighlights(repairablePumpComponent1, repairablePumpComponent2, repairableEngineComponent); yield return null; } while (repairablePumpComponent1.IsBelowRepairThreshold || repairablePumpComponent2.IsBelowRepairThreshold || repairableEngineComponent.IsBelowRepairThreshold);
|
||||
CheckHighlights(repairablePumpComponent1, repairablePumpComponent2, repairableEngineComponent);
|
||||
RemoveCompletedObjective(segments[10]);
|
||||
RemoveCompletedObjective(10);
|
||||
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.Complete"), ChatMessageType.Radio, null);
|
||||
|
||||
// END TUTORIAL
|
||||
|
||||
@@ -72,62 +72,114 @@ namespace Barotrauma.Tutorials
|
||||
private PowerContainer officer_subSuperCapacitor_2;
|
||||
|
||||
// Variables
|
||||
private string radioSpeakerName;
|
||||
private LocalizedString radioSpeakerName;
|
||||
private Character officer;
|
||||
private float superCapacitorRechargeRate = 10;
|
||||
private Sprite officer_gunIcon;
|
||||
private Color officer_gunIconColor;
|
||||
|
||||
public OfficerTutorial(XElement element) : base(element)
|
||||
public OfficerTutorial() : base("tutorial.securityofficertraining".ToIdentifier(),
|
||||
new Segment(
|
||||
"Mechanic.Equipment".ToIdentifier(),
|
||||
"Mechanic.EquipmentObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Mechanic.EquipmentText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Officer.MeleeWeapon".ToIdentifier(),
|
||||
"Officer.MeleeWeaponObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Officer.MeleeWeaponText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Officer.Crawler".ToIdentifier(),
|
||||
"Officer.CrawlerObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Officer.CrawlerText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Officer.SomethingBig".ToIdentifier(),
|
||||
"Officer.SomethingBigObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Officer.SomethingBigText".ToIdentifier(), Width = 700, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_loaders.webm", TextTag = "Officer.SomethingBigText".ToIdentifier(), Width = 700, Height = 80 }),
|
||||
new Segment(
|
||||
"Officer.Hammerhead".ToIdentifier(),
|
||||
"Officer.HammerheadObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Officer.HammerheadText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Officer.RangedWeapon".ToIdentifier(),
|
||||
"Officer.RangedWeaponObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Officer.RangedWeaponText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_ranged.webm", TextTag = "Officer.RangedWeaponText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Officer.Mudraptor".ToIdentifier(),
|
||||
"Officer.MudraptorObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Officer.MudraptorText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Officer.ArmSubmarine".ToIdentifier(),
|
||||
"Officer.ArmSubmarineObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Officer.ArmSubmarineText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }))
|
||||
{ }
|
||||
|
||||
protected override CharacterInfo GetCharacterInfo()
|
||||
{
|
||||
return new CharacterInfo(
|
||||
CharacterPrefab.HumanSpeciesName,
|
||||
jobOrJobPrefab: new Job(
|
||||
JobPrefab.Prefabs["securityofficer"], Rand.RandSync.Unsynced, 0,
|
||||
new Skill("medical".ToIdentifier(), 20),
|
||||
new Skill("weapons".ToIdentifier(), 70),
|
||||
new Skill("mechanical".ToIdentifier(), 20),
|
||||
new Skill("electrical".ToIdentifier(), 20),
|
||||
new Skill("helm".ToIdentifier(), 20)));
|
||||
}
|
||||
|
||||
public override void Start()
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
radioSpeakerName = TextManager.Get("Tutorial.Radio.Speaker");
|
||||
officer = Character.Controlled;
|
||||
|
||||
var handcuffs = FindOrGiveItem(officer, "handcuffs");
|
||||
var handcuffs = FindOrGiveItem(officer, "handcuffs".ToIdentifier());
|
||||
handcuffs.Unequip(officer);
|
||||
officer.Inventory.RemoveItem(handcuffs);
|
||||
|
||||
var stunbaton = FindOrGiveItem(officer, "stunbaton");
|
||||
var stunbaton = FindOrGiveItem(officer, "stunbaton".ToIdentifier());
|
||||
stunbaton.Unequip(officer);
|
||||
officer.Inventory.RemoveItem(stunbaton);
|
||||
|
||||
var smg = FindOrGiveItem(officer, "smg");
|
||||
var smg = FindOrGiveItem(officer, "smg".ToIdentifier());
|
||||
smg.Unequip(officer);
|
||||
officer.Inventory.RemoveItem(smg);
|
||||
|
||||
var divingknife = FindOrGiveItem(officer, "divingknife");
|
||||
var divingknife = FindOrGiveItem(officer, "divingknife".ToIdentifier());
|
||||
divingknife.Unequip(officer);
|
||||
officer.Inventory.RemoveItem(divingknife);
|
||||
|
||||
var steroids = FindOrGiveItem(officer, "steroids");
|
||||
var steroids = FindOrGiveItem(officer, "steroids".ToIdentifier());
|
||||
steroids.Unequip(officer);
|
||||
officer.Inventory.RemoveItem(steroids);
|
||||
|
||||
var ballistichelmet =
|
||||
officer.Inventory.FindItemByIdentifier("ballistichelmet1") ??
|
||||
officer.Inventory.FindItemByIdentifier("ballistichelmet2") ??
|
||||
FindOrGiveItem(officer, "ballistichelmet3");
|
||||
officer.Inventory.FindItemByIdentifier("ballistichelmet1".ToIdentifier()) ??
|
||||
officer.Inventory.FindItemByIdentifier("ballistichelmet2".ToIdentifier()) ??
|
||||
FindOrGiveItem(officer, "ballistichelmet3".ToIdentifier());
|
||||
ballistichelmet.Unequip(officer);
|
||||
officer.Inventory.RemoveItem(ballistichelmet);
|
||||
|
||||
var bodyarmor = FindOrGiveItem(officer, "bodyarmor");
|
||||
var bodyarmor = FindOrGiveItem(officer, "bodyarmor".ToIdentifier());
|
||||
bodyarmor.Unequip(officer);
|
||||
officer.Inventory.RemoveItem(bodyarmor);
|
||||
|
||||
var gunOrder = Order.GetPrefab("operateweapons");
|
||||
var gunOrder = OrderPrefab.Prefabs["operateweapons"];
|
||||
officer_gunIcon = gunOrder.SymbolSprite;
|
||||
officer_gunIconColor = gunOrder.Color;
|
||||
|
||||
var bandage = FindOrGiveItem(officer, "antibleeding1");
|
||||
var bandage = FindOrGiveItem(officer, "antibleeding1".ToIdentifier());
|
||||
bandage.Unequip(officer);
|
||||
officer.Inventory.RemoveItem(bandage);
|
||||
FindOrGiveItem(officer, "antibleeding1");
|
||||
FindOrGiveItem(officer, "antibleeding1".ToIdentifier());
|
||||
|
||||
// Other tutorial items
|
||||
tutorial_mechanicFinalDoorLight = Item.ItemList.Find(i => i.HasTag("tutorial_mechanicfinaldoorlight")).GetComponent<LightComponent>();
|
||||
@@ -222,7 +274,7 @@ namespace Barotrauma.Tutorials
|
||||
do { yield return null; } while (!officer_equipmentObjectiveSensor.MotionDetected);
|
||||
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Officer.Radio.Equipment"), ChatMessageType.Radio, null);
|
||||
yield return new WaitForSeconds(3f, false);
|
||||
//TriggerTutorialSegment(0, GameMain.Config.KeyBind(InputType.Select), GameMain.Config.KeyBind(InputType.Deselect)); // Retrieve equipment
|
||||
//TriggerTutorialSegment(0, GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Select], GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Deselect]); // Retrieve equipment
|
||||
SetHighlight(officer_equipmentCabinet.Item, true);
|
||||
bool firstSlotRemoved = false;
|
||||
bool secondSlotRemoved = false;
|
||||
@@ -260,24 +312,24 @@ namespace Barotrauma.Tutorials
|
||||
//RemoveCompletedObjective(segments[0]);
|
||||
SetHighlight(officer_equipmentCabinet.Item, false);
|
||||
do { yield return null; } while (IsSelectedItem(officer_equipmentCabinet.Item));
|
||||
TriggerTutorialSegment(1, GameMain.Config.KeyBindText(InputType.Aim), GameMain.Config.KeyBindText(InputType.Shoot)); // Equip melee weapon & armor
|
||||
TriggerTutorialSegment(1, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Aim), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Shoot)); // Equip melee weapon & armor
|
||||
do
|
||||
{
|
||||
if (!officer.HasEquippedItem("stunbaton"))
|
||||
if (!officer.HasEquippedItem("stunbaton".ToIdentifier()))
|
||||
{
|
||||
HighlightInventorySlot(officer.Inventory, "stunbaton", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(officer.Inventory, "stunbaton".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
}
|
||||
if (!officer.HasEquippedItem("bodyarmor"))
|
||||
if (!officer.HasEquippedItem("bodyarmor".ToIdentifier()))
|
||||
{
|
||||
HighlightInventorySlot(officer.Inventory, "bodyarmor", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(officer.Inventory, "bodyarmor".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
}
|
||||
if (!officer.HasEquippedItem("ballistichelmet1"))
|
||||
if (!officer.HasEquippedItem("ballistichelmet1".ToIdentifier()))
|
||||
{
|
||||
HighlightInventorySlot(officer.Inventory, "ballistichelmet1", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(officer.Inventory, "ballistichelmet1".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
}
|
||||
yield return new WaitForSeconds(1f, false);
|
||||
} while (!officer.HasEquippedItem("stunbaton") || !officer.HasEquippedItem("bodyarmor") || !officer.HasEquippedItem("ballistichelmet1"));
|
||||
RemoveCompletedObjective(segments[1]);
|
||||
} while (!officer.HasEquippedItem("stunbaton".ToIdentifier()) || !officer.HasEquippedItem("bodyarmor".ToIdentifier()) || !officer.HasEquippedItem("ballistichelmet1".ToIdentifier()));
|
||||
RemoveCompletedObjective(1);
|
||||
SetDoorAccess(officer_firstDoor, officer_firstDoorLight, true);
|
||||
|
||||
// Room 3
|
||||
@@ -285,7 +337,7 @@ namespace Barotrauma.Tutorials
|
||||
TriggerTutorialSegment(2);
|
||||
officer_crawler = SpawnMonster("crawler", officer_crawlerSpawnPos);
|
||||
do { yield return null; } while (!officer_crawler.IsDead);
|
||||
RemoveCompletedObjective(segments[2]);
|
||||
RemoveCompletedObjective(2);
|
||||
Heal(officer);
|
||||
yield return new WaitForSeconds(1f, false);
|
||||
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Officer.Radio.CrawlerDead"), ChatMessageType.Radio, null);
|
||||
@@ -305,7 +357,7 @@ namespace Barotrauma.Tutorials
|
||||
SetHighlight(officer_ammoShelf_2.Item, officer_coilgunLoader.Item.ExternalHighlight );
|
||||
if (IsSelectedItem(officer_coilgunLoader.Item))
|
||||
{
|
||||
HighlightInventorySlot(officer.Inventory, "coilgunammobox", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(officer.Inventory, "coilgunammobox".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
}
|
||||
yield return null;
|
||||
} while (officer_coilgunLoader.Inventory.GetItemAt(0) == null || officer_superCapacitor.RechargeSpeed < superCapacitorRechargeRate || officer_coilgunLoader.Inventory.GetItemAt(0).Condition == 0);
|
||||
@@ -313,9 +365,9 @@ namespace Barotrauma.Tutorials
|
||||
SetHighlight(officer_superCapacitor.Item, false);
|
||||
SetHighlight(officer_ammoShelf_1.Item, false);
|
||||
SetHighlight(officer_ammoShelf_2.Item, false);
|
||||
RemoveCompletedObjective(segments[3]);
|
||||
RemoveCompletedObjective(3);
|
||||
yield return new WaitForSeconds(2f, false);
|
||||
TriggerTutorialSegment(4, GameMain.Config.KeyBindText(InputType.Select), GameMain.Config.KeyBindText(InputType.Shoot), GameMain.Config.KeyBindText(InputType.Deselect)); // Kill hammerhead
|
||||
TriggerTutorialSegment(4, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Select), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Shoot), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Deselect)); // Kill hammerhead
|
||||
officer_hammerhead = SpawnMonster("hammerhead", officer_hammerheadSpawnPos);
|
||||
officer_hammerhead.Params.AI.AvoidAbyss = false;
|
||||
officer_hammerhead.Params.AI.StayInAbyss = false;
|
||||
@@ -348,7 +400,7 @@ namespace Barotrauma.Tutorials
|
||||
while(!officer_hammerhead.IsDead);
|
||||
Heal(officer);
|
||||
SetHighlight(officer_coilgunPeriscope, false);
|
||||
RemoveCompletedObjective(segments[4]);
|
||||
RemoveCompletedObjective(4);
|
||||
yield return new WaitForSeconds(1f, false);
|
||||
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Officer.Radio.HammerheadDead"), ChatMessageType.Radio, null);
|
||||
SetDoorAccess(officer_thirdDoor, officer_thirdDoorLight, true);
|
||||
@@ -357,16 +409,16 @@ namespace Barotrauma.Tutorials
|
||||
//do { yield return null; } while (!officer_rangedWeaponSensor.MotionDetected);
|
||||
do { yield return null; } while (!officer_thirdDoor.IsOpen);
|
||||
yield return new WaitForSeconds(3f, false);
|
||||
TriggerTutorialSegment(5, GameMain.Config.KeyBindText(InputType.Aim), GameMain.Config.KeyBindText(InputType.Shoot)); // Ranged weapons
|
||||
TriggerTutorialSegment(5, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Aim), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Shoot)); // Ranged weapons
|
||||
SetHighlight(officer_rangedWeaponHolder.Item, true);
|
||||
do { yield return null; } while (!officer_rangedWeaponHolder.Inventory.IsEmpty()); // Wait until looted
|
||||
SetHighlight(officer_rangedWeaponHolder.Item, false);
|
||||
do
|
||||
{
|
||||
HighlightInventorySlot(officer.Inventory, "shotgun", highlightColor, 0.5f, 0.5f, 0f);
|
||||
HighlightInventorySlot(officer.Inventory, "shotgun".ToIdentifier(), highlightColor, 0.5f, 0.5f, 0f);
|
||||
yield return null;
|
||||
} while (!officer.HasEquippedItem("shotgun")); // Wait until equipped
|
||||
ItemContainer shotGunChamber = officer.Inventory.FindItemByIdentifier("shotgun").GetComponent<ItemContainer>();
|
||||
} while (!officer.HasEquippedItem("shotgun".ToIdentifier())); // Wait until equipped
|
||||
ItemContainer shotGunChamber = officer.Inventory.FindItemByIdentifier("shotgun".ToIdentifier()).GetComponent<ItemContainer>();
|
||||
SetHighlight(officer_rangedWeaponCabinet.Item, true);
|
||||
do
|
||||
{
|
||||
@@ -392,13 +444,13 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
}
|
||||
|
||||
if (officer.Inventory.FindItemByIdentifier("shotgunshell") != null || (IsSelectedItem(officer_rangedWeaponCabinet.Item) && officer_rangedWeaponCabinet.Inventory.FindItemByIdentifier("shotgunshell") != null))
|
||||
if (officer.Inventory.FindItemByIdentifier("shotgunshell".ToIdentifier()) != null || (IsSelectedItem(officer_rangedWeaponCabinet.Item) && officer_rangedWeaponCabinet.Inventory.FindItemByIdentifier("shotgunshell".ToIdentifier()) != null))
|
||||
{
|
||||
HighlightInventorySlot(officer.Inventory, "shotgun", highlightColor, 0.5f, 0.5f, 0f);
|
||||
HighlightInventorySlot(officer.Inventory, "shotgun".ToIdentifier(), highlightColor, 0.5f, 0.5f, 0f);
|
||||
}
|
||||
yield return null;
|
||||
} while (!shotGunChamber.Inventory.IsFull(takeStacksIntoAccount: true)); // Wait until all six harpoons loaded
|
||||
RemoveCompletedObjective(segments[5]);
|
||||
RemoveCompletedObjective(5);
|
||||
SetHighlight(officer_rangedWeaponCabinet.Item, false);
|
||||
SetDoorAccess(officer_fourthDoor, officer_fourthDoorLight, true);
|
||||
|
||||
@@ -408,7 +460,7 @@ namespace Barotrauma.Tutorials
|
||||
officer_mudraptor = SpawnMonster("mudraptor", officer_mudraptorSpawnPos);
|
||||
do { yield return null; } while (!officer_mudraptor.IsDead);
|
||||
Heal(officer);
|
||||
RemoveCompletedObjective(segments[6]);
|
||||
RemoveCompletedObjective(6);
|
||||
SetDoorAccess(tutorial_securityFinalDoor, tutorial_securityFinalDoorLight, true);
|
||||
|
||||
// Submarine
|
||||
@@ -459,7 +511,7 @@ namespace Barotrauma.Tutorials
|
||||
officer.RemoveActiveObjectiveEntity(officer_subSuperCapacitor_2.Item);
|
||||
officer.RemoveActiveObjectiveEntity(officer_subAmmoBox_1);
|
||||
officer.RemoveActiveObjectiveEntity(officer_subAmmoBox_2);
|
||||
RemoveCompletedObjective(segments[7]);
|
||||
RemoveCompletedObjective(7);
|
||||
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Officer.Radio.Complete"), ChatMessageType.Radio, null);
|
||||
|
||||
yield return new WaitForSeconds(4f, false);
|
||||
|
||||
@@ -8,18 +8,21 @@ using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Tutorials
|
||||
{
|
||||
class ScenarioTutorial : Tutorial
|
||||
abstract class ScenarioTutorial : Tutorial
|
||||
{
|
||||
private CoroutineHandle tutorialCoroutine;
|
||||
|
||||
private Character character;
|
||||
private string spawnSub;
|
||||
private SpawnType spawnPointType;
|
||||
private string submarinePath;
|
||||
private string startOutpostPath;
|
||||
private string endOutpostPath;
|
||||
private string levelSeed;
|
||||
private string levelParams;
|
||||
|
||||
private const string submarinePath = "Content/Tutorials/Dugong_Tutorial.sub";
|
||||
private const string startOutpostPath = "Content/Tutorials/TutorialOutpost.sub";
|
||||
//private const string endOutpostPath = "";
|
||||
|
||||
private const string levelSeed = "nLoZLLtza";
|
||||
private const string levelParams = "ColdCavernsTutorial";
|
||||
|
||||
//private const string spawnSub = "startoutpost";
|
||||
private const SpawnType spawnPointType = SpawnType.Human;
|
||||
|
||||
private SubmarineInfo startOutpost = null;
|
||||
private SubmarineInfo endOutpost = null;
|
||||
@@ -31,34 +34,18 @@ namespace Barotrauma.Tutorials
|
||||
protected Color highlightColor = Color.OrangeRed;
|
||||
protected Color uiHighlightColor = new Color(150, 50, 0);
|
||||
protected Color buttonHighlightColor = new Color(255, 100, 0);
|
||||
protected Color inaccessibleColor = GUI.Style.Red;
|
||||
protected Color accessibleColor = GUI.Style.Green;
|
||||
protected Color inaccessibleColor = GUIStyle.Red;
|
||||
protected Color accessibleColor = GUIStyle.Green;
|
||||
|
||||
public ScenarioTutorial(XElement element) : base(element)
|
||||
{
|
||||
submarinePath = element.GetAttributeString("submarinepath", "");
|
||||
startOutpostPath = element.GetAttributeString("startoutpostpath", "");
|
||||
endOutpostPath = element.GetAttributeString("endoutpostpath", "");
|
||||
protected ScenarioTutorial(Identifier identifier, params Segment[] segments) : base(identifier, segments) { }
|
||||
|
||||
levelSeed = element.GetAttributeString("levelseed", "tuto");
|
||||
levelParams = element.GetAttributeString("levelparams", "");
|
||||
|
||||
spawnSub = element.GetAttributeString("spawnsub", "");
|
||||
Enum.TryParse(element.GetAttributeString("spawnpointtype", "Human"), true, out spawnPointType);
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
currentTutorialCompleted = false;
|
||||
GameMain.Instance.ShowLoading(Loading());
|
||||
}
|
||||
|
||||
private IEnumerable<CoroutineStatus> Loading()
|
||||
protected abstract void Initialize();
|
||||
|
||||
protected override IEnumerable<CoroutineStatus> Loading()
|
||||
{
|
||||
SubmarineInfo subInfo = new SubmarineInfo(submarinePath);
|
||||
|
||||
LevelGenerationParams generationParams = LevelGenerationParams.LevelParams.Find(p => p.Identifier.Equals(levelParams, StringComparison.OrdinalIgnoreCase));
|
||||
LevelGenerationParams generationParams = LevelGenerationParams.LevelParams.Find(p => p.Identifier == levelParams);
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
@@ -68,18 +55,18 @@ namespace Barotrauma.Tutorials
|
||||
if (generationParams != null)
|
||||
{
|
||||
Biome biome =
|
||||
LevelGenerationParams.GetBiomes().FirstOrDefault(b => generationParams.AllowedBiomes.Contains(b)) ??
|
||||
LevelGenerationParams.GetBiomes().First();
|
||||
Biome.Prefabs.FirstOrDefault(b => generationParams.AllowedBiomeIdentifiers.Contains(b.Identifier)) ??
|
||||
Biome.Prefabs.First();
|
||||
|
||||
if (!string.IsNullOrEmpty(startOutpostPath))
|
||||
{
|
||||
startOutpost = new SubmarineInfo(startOutpostPath);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(endOutpostPath))
|
||||
/*if (!string.IsNullOrEmpty(endOutpostPath))
|
||||
{
|
||||
endOutpost = new SubmarineInfo(endOutpostPath);
|
||||
}
|
||||
}*/
|
||||
|
||||
LevelData tutorialLevel = new LevelData(levelSeed, 0, 0, generationParams, biome);
|
||||
GameMain.GameSession.StartRound(tutorialLevel, startOutpost: startOutpost, endOutpost: endOutpost);
|
||||
@@ -93,12 +80,6 @@ namespace Barotrauma.Tutorials
|
||||
GameMain.GameSession.EventManager.Enabled = false;
|
||||
GameMain.GameScreen.Select();
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
public override void Start()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
Submarine.MainSub.GodMode = true;
|
||||
foreach (Structure wall in Structure.WallList)
|
||||
@@ -109,16 +90,15 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
}
|
||||
|
||||
CharacterInfo charInfo = configElement.Element("Character") == null ?
|
||||
new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("engineer")) :
|
||||
new CharacterInfo(configElement.Element("Character"));
|
||||
CharacterInfo charInfo = GetCharacterInfo();
|
||||
|
||||
WayPoint wayPoint = GetSpawnPoint(charInfo);
|
||||
|
||||
if (wayPoint == null)
|
||||
{
|
||||
DebugConsole.ThrowError("A waypoint with the spawntype \"" + spawnPointType + "\" is required for the tutorial event");
|
||||
return;
|
||||
yield return CoroutineStatus.Failure;
|
||||
yield break;
|
||||
}
|
||||
|
||||
character = Character.Create(charInfo, wayPoint.WorldPosition, "", isRemotePlayer: false, hasAi: false);
|
||||
@@ -126,11 +106,12 @@ namespace Barotrauma.Tutorials
|
||||
Character.Controlled = character;
|
||||
character.GiveJobItems(null);
|
||||
|
||||
var idCard = character.Inventory.FindItemByIdentifier("idcard");
|
||||
var idCard = character.Inventory.FindItemByIdentifier("idcard".ToIdentifier());
|
||||
if (idCard == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Item prefab \"ID Card\" not found!");
|
||||
return;
|
||||
yield return CoroutineStatus.Failure;
|
||||
yield break;
|
||||
}
|
||||
idCard.AddTag("com");
|
||||
idCard.AddTag("eng");
|
||||
@@ -145,8 +126,14 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
|
||||
tutorialCoroutine = CoroutineManager.StartCoroutine(UpdateState());
|
||||
|
||||
Initialize();
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
protected abstract CharacterInfo GetCharacterInfo();
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
{
|
||||
if (!currentTutorialCompleted)
|
||||
@@ -157,7 +144,7 @@ namespace Barotrauma.Tutorials
|
||||
|
||||
private WayPoint GetSpawnPoint(CharacterInfo charInfo)
|
||||
{
|
||||
Submarine spawnSub = null;
|
||||
/*Submarine spawnSub = null;
|
||||
|
||||
if (this.spawnSub != string.Empty)
|
||||
{
|
||||
@@ -175,15 +162,15 @@ namespace Barotrauma.Tutorials
|
||||
spawnSub = Submarine.MainSub;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}*/
|
||||
Submarine spawnSub = Level.Loaded.StartOutpost;
|
||||
return WayPoint.GetRandom(spawnPointType, charInfo.Job?.Prefab, spawnSub);
|
||||
}
|
||||
|
||||
protected bool HasOrder(Character character, string identifier, string option = null)
|
||||
{
|
||||
var currentOrderInfo = character.GetCurrentOrderWithTopPriority();
|
||||
if (currentOrderInfo?.Order?.Identifier == identifier)
|
||||
if (currentOrderInfo?.Identifier == identifier)
|
||||
{
|
||||
if (option == null)
|
||||
{
|
||||
@@ -191,7 +178,7 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
else
|
||||
{
|
||||
return currentOrderInfo?.OrderOption == option;
|
||||
return currentOrderInfo?.Option == option;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,7 +254,7 @@ namespace Barotrauma.Tutorials
|
||||
|
||||
yield return new WaitForSeconds(3.0f);
|
||||
|
||||
var messageBox = new GUIMessageBox(TextManager.Get("Tutorial.TryAgainHeader"), TextManager.Get("Tutorial.TryAgain"), new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||
var messageBox = new GUIMessageBox(TextManager.Get("Tutorial.TryAgainHeader"), TextManager.Get("Tutorial.TryAgain"), new LocalizedString[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||
|
||||
messageBox.Buttons[0].OnClicked += Restart;
|
||||
messageBox.Buttons[0].OnClicked += messageBox.Close;
|
||||
@@ -303,7 +290,7 @@ namespace Barotrauma.Tutorials
|
||||
character.SetStun(0.0f, true);
|
||||
}
|
||||
|
||||
protected Item FindOrGiveItem(Character character, string identifier)
|
||||
protected Item FindOrGiveItem(Character character, Identifier identifier)
|
||||
{
|
||||
var item = character.Inventory.FindItemByIdentifier(identifier);
|
||||
if (item != null && !item.Removed) { return item; }
|
||||
|
||||
@@ -7,189 +7,128 @@ using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.Extensions;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace Barotrauma.Tutorials
|
||||
{
|
||||
enum TutorialContentType { None = 0, Video = 1, ManualVideo = 2, TextOnly = 3 };
|
||||
|
||||
/// <summary>
|
||||
/// If you're seeing this and are currently working on improving the tutorials, consider
|
||||
/// deleting this class and all that derive from it, and starting from scratch.
|
||||
/// </summary>
|
||||
abstract class Tutorial
|
||||
{
|
||||
#region Tutorial variables
|
||||
public static bool Initialized = false;
|
||||
public static bool ContentRunning = false;
|
||||
public static List<Tutorial> Tutorials;
|
||||
#region Constants
|
||||
public const string PlayableContentPath = "Content/Tutorials/TutorialVideos/";
|
||||
#endregion
|
||||
|
||||
#region Tutorial variables
|
||||
public static ImmutableHashSet<Type> Types;
|
||||
static Tutorial()
|
||||
{
|
||||
Types = ReflectionUtils.GetDerivedNonAbstract<Tutorial>()
|
||||
.ToImmutableHashSet();
|
||||
}
|
||||
|
||||
public readonly Identifier Identifier;
|
||||
|
||||
public LocalizedString DisplayName { get; }
|
||||
|
||||
public bool ContentRunning { get; protected set; }
|
||||
|
||||
protected bool started = false;
|
||||
protected GUIComponent infoBox;
|
||||
private Action infoBoxClosedCallback;
|
||||
protected XElement configElement;
|
||||
|
||||
protected VideoPlayer videoPlayer;
|
||||
protected enum TutorialContentTypes { None = 0, Video = 1, ManualVideo = 2, TextOnly = 3 };
|
||||
protected string playableContentPath;
|
||||
protected Point screenResolution;
|
||||
protected WindowMode windowMode;
|
||||
protected float prevUIScale;
|
||||
|
||||
private GUIFrame holderFrame, objectiveFrame;
|
||||
private List<TutorialSegment> activeObjectives = new List<TutorialSegment>();
|
||||
private string objectiveTranslated;
|
||||
private readonly List<Index> activeObjectives;
|
||||
private readonly LocalizedString objectiveTranslated;
|
||||
|
||||
protected TutorialSegment activeContentSegment;
|
||||
protected List<TutorialSegment> segments;
|
||||
protected readonly ImmutableArray<Segment> segments;
|
||||
protected Index activeContentSegmentIndex;
|
||||
protected Segment activeContentSegment => segments[activeContentSegmentIndex];
|
||||
|
||||
protected class TutorialSegment
|
||||
protected class Segment
|
||||
{
|
||||
public string Id;
|
||||
public string Objective;
|
||||
public TutorialContentTypes ContentType;
|
||||
public XElement TextContent;
|
||||
public XElement VideoContent;
|
||||
public struct Text
|
||||
{
|
||||
public Identifier Tag;
|
||||
public int Width;
|
||||
public int Height;
|
||||
public Anchor Anchor;
|
||||
}
|
||||
|
||||
public struct Video
|
||||
{
|
||||
public string File;
|
||||
public Identifier TextTag;
|
||||
public int Width;
|
||||
public int Height;
|
||||
}
|
||||
|
||||
public bool IsTriggered;
|
||||
public GUIButton ReplayButton;
|
||||
public GUITextBlock LinkedTitle, LinkedText;
|
||||
public object[] Args;
|
||||
public LocalizedString Objective;
|
||||
|
||||
public TutorialSegment(XElement config)
|
||||
public readonly Identifier Id;
|
||||
public readonly Text? TextContent;
|
||||
public readonly Video? VideoContent;
|
||||
public readonly TutorialContentType ContentType;
|
||||
|
||||
public Segment(Identifier id, Identifier objectiveTextTag, TutorialContentType contentType, Text? textContent = null, Video? videoContent = null)
|
||||
{
|
||||
Id = config.GetAttributeString("id", "Missing ID");
|
||||
Objective = TextManager.Get(config.GetAttributeString("objective", string.Empty), true);
|
||||
Enum.TryParse(config.GetAttributeString("contenttype", "None"), true, out ContentType);
|
||||
IsTriggered = config.GetAttributeBool("istriggered", false);
|
||||
Id = id;
|
||||
Objective = TextManager.ParseInputTypes(TextManager.Get(objectiveTextTag));
|
||||
ContentType = contentType;
|
||||
TextContent = textContent;
|
||||
VideoContent = videoContent;
|
||||
|
||||
switch (ContentType)
|
||||
{
|
||||
case TutorialContentTypes.None:
|
||||
break;
|
||||
case TutorialContentTypes.Video:
|
||||
case TutorialContentTypes.ManualVideo:
|
||||
VideoContent = config.Element("Video");
|
||||
TextContent = config.Element("Text");
|
||||
break;
|
||||
case TutorialContentTypes.TextOnly:
|
||||
TextContent = config.Element("Text");
|
||||
break;
|
||||
}
|
||||
IsTriggered = false;
|
||||
}
|
||||
}
|
||||
|
||||
public string Identifier
|
||||
{
|
||||
get;
|
||||
protected set;
|
||||
}
|
||||
|
||||
public string DisplayName
|
||||
{
|
||||
get;
|
||||
protected set;
|
||||
}
|
||||
|
||||
private bool completed;
|
||||
public bool Completed
|
||||
{
|
||||
get { return completed; }
|
||||
protected set
|
||||
{
|
||||
if (completed == value) return;
|
||||
if (completed == value) { return; }
|
||||
completed = value;
|
||||
GameMain.Config.SaveNewPlayerConfig();
|
||||
if (value)
|
||||
{
|
||||
CompletedTutorials.Instance.Add(Identifier);
|
||||
}
|
||||
GameSettings.SaveCurrentConfig();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Tutorial Controls
|
||||
public static void Init()
|
||||
protected Tutorial(Identifier identifier, params Segment[] segments)
|
||||
{
|
||||
Tutorials = new List<Tutorial>();
|
||||
foreach (ContentFile file in GameMain.Instance.GetFilesOfType(ContentType.Tutorials))
|
||||
{
|
||||
XDocument doc = XMLExtensions.TryLoadXml(file.Path);
|
||||
if (doc?.Root == null) continue;
|
||||
|
||||
foreach (XElement element in doc.Root.Elements())
|
||||
{
|
||||
Tutorial newTutorial = Load(element);
|
||||
if (newTutorial != null) Tutorials.Add(newTutorial);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Tutorial Load(XElement element)
|
||||
{
|
||||
Type t;
|
||||
string type = element.Name.ToString().ToLowerInvariant();
|
||||
try
|
||||
{
|
||||
// Get the type of a specified class.
|
||||
t = Type.GetType("Barotrauma.Tutorials." + type + "", false, true);
|
||||
if (t == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Could not find tutorial type \"" + type + "\"");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Could not find tutorial type \"" + type + "\"", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
ConstructorInfo constructor;
|
||||
try
|
||||
{
|
||||
if (!t.IsSubclassOf(typeof(Tutorial))) return null;
|
||||
constructor = t.GetConstructor(new Type[] { typeof(XElement) });
|
||||
if (constructor == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Could not find the constructor of tutorial type \"" + type + "\"");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Could not find the constructor of tutorial type \"" + type + "\"", e);
|
||||
return null;
|
||||
}
|
||||
Tutorial tutorial = null;
|
||||
try
|
||||
{
|
||||
object component = constructor.Invoke(new object[] { element });
|
||||
tutorial = (Tutorial)component;
|
||||
}
|
||||
catch (TargetInvocationException e)
|
||||
{
|
||||
DebugConsole.ThrowError("Error while loading tutorial of the type " + t + ".", e.InnerException);
|
||||
}
|
||||
|
||||
return tutorial;
|
||||
}
|
||||
|
||||
public Tutorial(XElement element)
|
||||
{
|
||||
configElement = element;
|
||||
Identifier = element.GetAttributeString("identifier", "unknown");
|
||||
Identifier = identifier;
|
||||
this.segments = segments.ToImmutableArray();
|
||||
DisplayName = TextManager.Get(Identifier);
|
||||
completed = GameMain.Config.CompletedTutorialNames.Contains(Identifier);
|
||||
playableContentPath = element.GetAttributeString("playablecontentpath", "");
|
||||
|
||||
segments = new List<TutorialSegment>();
|
||||
|
||||
foreach (var segment in element.Elements("Segment"))
|
||||
{
|
||||
segments.Add(new TutorialSegment(segment));
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Initialize()
|
||||
{
|
||||
if (Initialized) return;
|
||||
Initialized = true;
|
||||
videoPlayer = new VideoPlayer();
|
||||
}
|
||||
|
||||
public virtual void Start()
|
||||
{
|
||||
activeObjectives.Clear();
|
||||
activeObjectives = new List<Index>();
|
||||
objectiveTranslated = TextManager.Get("Tutorial.Objective");
|
||||
}
|
||||
|
||||
protected abstract IEnumerable<CoroutineStatus> Loading();
|
||||
|
||||
public void Start()
|
||||
{
|
||||
videoPlayer = new VideoPlayer();
|
||||
GameMain.Instance.ShowLoading(Loading());
|
||||
|
||||
activeObjectives.Clear();
|
||||
CreateObjectiveFrame();
|
||||
|
||||
// Setup doors: Clear all requirements, unless the door is setup as locked.
|
||||
@@ -208,7 +147,7 @@ namespace Barotrauma.Tutorials
|
||||
|
||||
public virtual void AddToGUIUpdateList()
|
||||
{
|
||||
if (GameMain.GraphicsWidth != screenResolution.X || GameMain.GraphicsHeight != screenResolution.Y || prevUIScale != GUI.Scale || GameMain.Config.WindowMode != windowMode)
|
||||
if (GameMain.GraphicsWidth != screenResolution.X || GameMain.GraphicsHeight != screenResolution.Y || prevUIScale != GUI.Scale || GameSettings.CurrentConfig.Graphics.DisplayMode != windowMode)
|
||||
{
|
||||
CreateObjectiveFrame();
|
||||
}
|
||||
@@ -255,74 +194,69 @@ namespace Barotrauma.Tutorials
|
||||
protected bool Restart(GUIButton button, object obj)
|
||||
{
|
||||
GUI.PreventPauseMenuToggle = false;
|
||||
TutorialMode.StartTutorial(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected virtual void TriggerTutorialSegment(int index, params object[] args)
|
||||
protected virtual void TriggerTutorialSegment(Index index, params object[] args)
|
||||
{
|
||||
Inventory.DraggingItems.Clear();
|
||||
ContentRunning = true;
|
||||
activeContentSegment = segments[index];
|
||||
activeContentSegmentIndex = index;
|
||||
segments[index].Args = args;
|
||||
|
||||
string tutorialText = TextManager.GetFormatted(activeContentSegment.TextContent.GetAttributeString("tag", ""), true, args);
|
||||
LocalizedString tutorialText = TextManager.GetFormatted(segments[index].TextContent.Value.Tag, args);
|
||||
tutorialText = TextManager.ParseInputTypes(tutorialText);
|
||||
string objectiveText = string.Empty;
|
||||
LocalizedString objectiveText = string.Empty;
|
||||
|
||||
if (!string.IsNullOrEmpty(activeContentSegment.Objective))
|
||||
if (!segments[index].Objective.IsNullOrEmpty())
|
||||
{
|
||||
if (args.Length == 0)
|
||||
{
|
||||
objectiveText = activeContentSegment.Objective;
|
||||
objectiveText = segments[index].Objective;
|
||||
}
|
||||
else
|
||||
{
|
||||
objectiveText = string.Format(activeContentSegment.Objective, args);
|
||||
objectiveText = TextManager.GetFormatted(segments[index].Objective, args);
|
||||
}
|
||||
objectiveText = TextManager.ParseInputTypes(objectiveText);
|
||||
activeContentSegment.Objective = objectiveText;
|
||||
segments[index].Objective = objectiveText;
|
||||
}
|
||||
else
|
||||
{
|
||||
activeContentSegment.IsTriggered = true; // Complete at this stage only if no related objective
|
||||
segments[index].IsTriggered = true; // Complete at this stage only if no related objective
|
||||
}
|
||||
|
||||
|
||||
switch (activeContentSegment.ContentType)
|
||||
switch (segments[index].ContentType)
|
||||
{
|
||||
case TutorialContentTypes.None:
|
||||
case TutorialContentType.None:
|
||||
break;
|
||||
case TutorialContentTypes.Video:
|
||||
case TutorialContentType.Video:
|
||||
infoBox = CreateInfoFrame(TextManager.Get(activeContentSegment.Id), tutorialText,
|
||||
activeContentSegment.TextContent.GetAttributeInt("width", 300),
|
||||
activeContentSegment.TextContent.GetAttributeInt("height", 80),
|
||||
activeContentSegment.TextContent.GetAttributeString("anchor", "Center"), true, () => LoadVideo(activeContentSegment));
|
||||
activeContentSegment.TextContent.Value.Width,
|
||||
activeContentSegment.TextContent.Value.Height,
|
||||
activeContentSegment.TextContent.Value.Anchor, true, () => LoadVideo(activeContentSegment));
|
||||
break;
|
||||
case TutorialContentTypes.ManualVideo:
|
||||
case TutorialContentType.ManualVideo:
|
||||
infoBox = CreateInfoFrame(TextManager.Get(activeContentSegment.Id), tutorialText,
|
||||
activeContentSegment.TextContent.GetAttributeInt("width", 300),
|
||||
activeContentSegment.TextContent.GetAttributeInt("height", 80),
|
||||
activeContentSegment.TextContent.GetAttributeString("anchor", "Center"), true, StopCurrentContentSegment, () => LoadVideo(activeContentSegment));
|
||||
activeContentSegment.TextContent.Value.Width,
|
||||
activeContentSegment.TextContent.Value.Height,
|
||||
activeContentSegment.TextContent.Value.Anchor, true, StopCurrentContentSegment, () => LoadVideo(activeContentSegment));
|
||||
break;
|
||||
case TutorialContentTypes.TextOnly:
|
||||
case TutorialContentType.TextOnly:
|
||||
infoBox = CreateInfoFrame(TextManager.Get(activeContentSegment.Id), tutorialText,
|
||||
activeContentSegment.TextContent.GetAttributeInt("width", 300),
|
||||
activeContentSegment.TextContent.GetAttributeInt("height", 80),
|
||||
activeContentSegment.TextContent.GetAttributeString("anchor", "Center"), true, StopCurrentContentSegment);
|
||||
activeContentSegment.TextContent.Value.Width,
|
||||
activeContentSegment.TextContent.Value.Height,
|
||||
activeContentSegment.TextContent.Value.Anchor, true, StopCurrentContentSegment);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Stop()
|
||||
{
|
||||
started = ContentRunning = Initialized = false;
|
||||
ContentRunning = false;
|
||||
infoBox = null;
|
||||
if (videoPlayer != null)
|
||||
{
|
||||
videoPlayer.Remove();
|
||||
videoPlayer = null;
|
||||
}
|
||||
videoPlayer.Remove();
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -334,50 +268,51 @@ namespace Barotrauma.Tutorials
|
||||
|
||||
for (int i = 0; i < activeObjectives.Count; i++)
|
||||
{
|
||||
CreateObjectiveGUI(activeObjectives[i], i, activeObjectives[i].ContentType);
|
||||
CreateObjectiveGUI(activeObjectives[i], i, segments[activeObjectives[i]].ContentType);
|
||||
}
|
||||
|
||||
screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||
windowMode = GameMain.Config.WindowMode;
|
||||
windowMode = GameSettings.CurrentConfig.Graphics.DisplayMode;
|
||||
prevUIScale = GUI.Scale;
|
||||
}
|
||||
|
||||
protected void StopCurrentContentSegment()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(activeContentSegment.Objective))
|
||||
if (!activeContentSegment.Objective.IsNullOrEmpty())
|
||||
{
|
||||
AddNewObjective(activeContentSegment, activeContentSegment.ContentType);
|
||||
AddNewObjective(activeContentSegmentIndex, activeContentSegment.ContentType);
|
||||
}
|
||||
|
||||
activeContentSegment = null;
|
||||
ContentRunning = false;
|
||||
activeContentSegmentIndex = Index.End;
|
||||
}
|
||||
|
||||
protected virtual void CheckActiveObjectives(TutorialSegment objective, float deltaTime)
|
||||
protected virtual void CheckActiveObjectives(Index objective, float deltaTime)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected bool HasObjective(TutorialSegment segment)
|
||||
protected bool HasObjective(Index segment)
|
||||
{
|
||||
return activeObjectives.Contains(segment);
|
||||
}
|
||||
|
||||
protected void AddNewObjective(TutorialSegment segment, TutorialContentTypes type)
|
||||
protected void AddNewObjective(Index segment, TutorialContentType type)
|
||||
{
|
||||
activeObjectives.Add(segment);
|
||||
CreateObjectiveGUI(segment, activeObjectives.Count - 1, type);
|
||||
}
|
||||
|
||||
private void CreateObjectiveGUI(TutorialSegment segment, int index, TutorialContentTypes type)
|
||||
private void CreateObjectiveGUI(Index segmentIndex, int index, TutorialContentType type)
|
||||
{
|
||||
string objectiveText = TextManager.ParseInputTypes(segment.Objective);
|
||||
Point replayButtonSize = new Point((int)(GUI.LargeFont.MeasureString(objectiveText).X), (int)(GUI.LargeFont.MeasureString(objectiveText).Y * 1.45f));
|
||||
var segment = segments[segmentIndex];
|
||||
LocalizedString objectiveText = TextManager.ParseInputTypes(segment.Objective);
|
||||
Point replayButtonSize = new Point((int)(GUIStyle.LargeFont.MeasureString(objectiveText).X), (int)(GUIStyle.LargeFont.MeasureString(objectiveText).Y * 1.45f));
|
||||
|
||||
segment.ReplayButton = new GUIButton(new RectTransform(replayButtonSize, objectiveFrame.RectTransform, Anchor.TopLeft, Pivot.TopLeft) { AbsoluteOffset = new Point(0, (replayButtonSize.Y + (int)(20f * GUI.Scale)) * index) }, style: null);
|
||||
segment.ReplayButton.OnClicked += (GUIButton btn, object userdata) =>
|
||||
{
|
||||
if (type == TutorialContentTypes.Video)
|
||||
if (type == TutorialContentType.Video)
|
||||
{
|
||||
ReplaySegmentVideo(segment);
|
||||
}
|
||||
@@ -388,23 +323,23 @@ namespace Barotrauma.Tutorials
|
||||
return true;
|
||||
};
|
||||
|
||||
string objectiveTitleText = TextManager.ParseInputTypes(objectiveTranslated);
|
||||
int yOffset = (int)((GUI.SubHeadingFont.MeasureString(objectiveTitleText).Y + 5));
|
||||
segment.LinkedTitle = new GUITextBlock(new RectTransform(new Point((int)GUI.SubHeadingFont.MeasureString(objectiveTitleText).X, yOffset), segment.ReplayButton.RectTransform, Anchor.CenterLeft, Pivot.BottomLeft) /*{ AbsoluteOffset = new Point((int)(-10 * GUI.Scale), 0) }*/,
|
||||
objectiveTitleText, textColor: Color.White, font: GUI.SubHeadingFont, textAlignment: Alignment.CenterLeft)
|
||||
LocalizedString objectiveTitleText = TextManager.ParseInputTypes(objectiveTranslated);
|
||||
int yOffset = (int)((GUIStyle.SubHeadingFont.MeasureString(objectiveTitleText).Y + 5));
|
||||
segment.LinkedTitle = new GUITextBlock(new RectTransform(new Point((int)GUIStyle.SubHeadingFont.MeasureString(objectiveTitleText).X, yOffset), segment.ReplayButton.RectTransform, Anchor.CenterLeft, Pivot.BottomLeft) /*{ AbsoluteOffset = new Point((int)(-10 * GUI.Scale), 0) }*/,
|
||||
objectiveTitleText, textColor: Color.White, font: GUIStyle.SubHeadingFont, textAlignment: Alignment.CenterLeft)
|
||||
{
|
||||
ForceUpperCase = true
|
||||
ForceUpperCase = ForceUpperCase.Yes
|
||||
};
|
||||
|
||||
segment.LinkedText = new GUITextBlock(new RectTransform(new Point((int)GUI.LargeFont.MeasureString(objectiveText).X, yOffset), segment.ReplayButton.RectTransform, Anchor.CenterLeft, Pivot.TopLeft) /*{ AbsoluteOffset = new Point((int)(10 * GUI.Scale), 0) }*/,
|
||||
objectiveText, textColor: new Color(4, 180, 108), font: GUI.LargeFont, textAlignment: Alignment.CenterLeft);
|
||||
segment.LinkedText = new GUITextBlock(new RectTransform(new Point((int)GUIStyle.LargeFont.MeasureString(objectiveText).X, yOffset), segment.ReplayButton.RectTransform, Anchor.CenterLeft, Pivot.TopLeft) /*{ AbsoluteOffset = new Point((int)(10 * GUI.Scale), 0) }*/,
|
||||
objectiveText, textColor: new Color(4, 180, 108), font: GUIStyle.LargeFont, textAlignment: Alignment.CenterLeft);
|
||||
|
||||
segment.LinkedTitle.Color = segment.LinkedTitle.HoverColor = segment.LinkedTitle.PressedColor = segment.LinkedTitle.SelectedColor = Color.Transparent;
|
||||
segment.LinkedText.Color = segment.LinkedText.HoverColor = segment.LinkedText.PressedColor = segment.LinkedText.SelectedColor = Color.Transparent;
|
||||
segment.ReplayButton.Color = segment.ReplayButton.HoverColor = segment.ReplayButton.PressedColor = segment.ReplayButton.SelectedColor = Color.Transparent;
|
||||
}
|
||||
|
||||
private void ReplaySegmentVideo(TutorialSegment segment)
|
||||
private void ReplaySegmentVideo(Segment segment)
|
||||
{
|
||||
if (ContentRunning) return;
|
||||
Inventory.DraggingItems.Clear();
|
||||
@@ -413,30 +348,31 @@ namespace Barotrauma.Tutorials
|
||||
//videoPlayer.LoadContent(playableContentPath, new VideoPlayer.VideoSettings(segment.VideoContent), new VideoPlayer.TextSettings(segment.VideoContent), segment.Id, true, callback: () => ContentRunning = false);
|
||||
}
|
||||
|
||||
private void ShowSegmentText(TutorialSegment segment)
|
||||
private void ShowSegmentText(Segment segment)
|
||||
{
|
||||
if (ContentRunning) return;
|
||||
Inventory.DraggingItems.Clear();
|
||||
ContentRunning = true;
|
||||
|
||||
string tutorialText = TextManager.GetFormatted(segment.TextContent.GetAttributeString("tag", ""), true, segment.Args);
|
||||
LocalizedString tutorialText = TextManager.GetFormatted(segment.TextContent.Value.Tag, segment.Args);
|
||||
|
||||
Action videoAction = null;
|
||||
|
||||
if (segment.ContentType != TutorialContentTypes.TextOnly)
|
||||
if (segment.ContentType != TutorialContentType.TextOnly)
|
||||
{
|
||||
videoAction = () => LoadVideo(segment);
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame(TextManager.Get(segment.Id), tutorialText,
|
||||
segment.TextContent.GetAttributeInt("width", 300),
|
||||
segment.TextContent.GetAttributeInt("height", 80),
|
||||
segment.TextContent.GetAttributeString("anchor", "Center"), true, () => ContentRunning = false, videoAction);
|
||||
segment.TextContent.Value.Width,
|
||||
segment.TextContent.Value.Height,
|
||||
segment.TextContent.Value.Anchor, true, () => ContentRunning = false, videoAction);
|
||||
}
|
||||
|
||||
protected void RemoveCompletedObjective(TutorialSegment segment)
|
||||
protected void RemoveCompletedObjective(Index segmentIndex)
|
||||
{
|
||||
if (!HasObjective(segment)) return;
|
||||
if (!HasObjective(segmentIndex)) return;
|
||||
var segment = segments[segmentIndex];
|
||||
segment.IsTriggered = true;
|
||||
segment.ReplayButton.OnClicked = null;
|
||||
|
||||
@@ -467,18 +403,20 @@ namespace Barotrauma.Tutorials
|
||||
GUIImage stroke = new GUIImage(rectTB, "Stroke");
|
||||
stroke.Color = stroke.SelectedColor = stroke.HoverColor = stroke.PressedColor = color;
|
||||
|
||||
CoroutineManager.StartCoroutine(WaitForObjectiveEnd(segment));
|
||||
CoroutineManager.StartCoroutine(WaitForObjectiveEnd(segmentIndex));
|
||||
}
|
||||
|
||||
private IEnumerable<CoroutineStatus> WaitForObjectiveEnd(TutorialSegment objective)
|
||||
private IEnumerable<CoroutineStatus> WaitForObjectiveEnd(Index objectiveIndex)
|
||||
{
|
||||
var objective = segments[objectiveIndex];
|
||||
yield return new WaitForSeconds(2.0f);
|
||||
objectiveFrame.RemoveChild(objective.ReplayButton);
|
||||
activeObjectives.Remove(objective);
|
||||
activeObjectives.Remove(objectiveIndex);
|
||||
|
||||
for (int i = 0; i < activeObjectives.Count; i++)
|
||||
{
|
||||
activeObjectives[i].ReplayButton.RectTransform.AbsoluteOffset = new Point(0, (activeObjectives[i].ReplayButton.Rect.Height + 20) * i);
|
||||
var activeObjective = segments[activeObjectives[i]];
|
||||
activeObjective.ReplayButton.RectTransform.AbsoluteOffset = new Point(0, (activeObjective.ReplayButton.Rect.Height + 20) * i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -492,32 +430,25 @@ namespace Barotrauma.Tutorials
|
||||
return true;
|
||||
}
|
||||
|
||||
protected GUIComponent CreateInfoFrame(string title, string text, int width = 300, int height = 80, string anchorStr = "", bool hasButton = false, Action callback = null, Action showVideo = null)
|
||||
protected GUIComponent CreateInfoFrame(LocalizedString title, LocalizedString text, int width = 300, int height = 80, Anchor anchor = Anchor.TopRight, bool hasButton = false, Action callback = null, Action showVideo = null)
|
||||
{
|
||||
if (hasButton) height += 60;
|
||||
|
||||
Anchor anchor = Anchor.TopRight;
|
||||
|
||||
if (anchorStr != string.Empty)
|
||||
{
|
||||
Enum.TryParse(anchorStr, out anchor);
|
||||
}
|
||||
|
||||
width = (int)(width * GUI.Scale);
|
||||
height = (int)(height * GUI.Scale);
|
||||
|
||||
string wrappedText = ToolBox.WrapText(text, width, GUI.Font);
|
||||
height += (int)GUI.Font.MeasureString(wrappedText).Y;
|
||||
LocalizedString wrappedText = ToolBox.WrapText(text, width, GUIStyle.Font);
|
||||
height += (int)GUIStyle.Font.MeasureString(wrappedText).Y;
|
||||
|
||||
if (title.Length > 0)
|
||||
{
|
||||
height += (int)GUI.Font.MeasureString(title).Y + (int)(150 * GUI.Scale);
|
||||
height += (int)GUIStyle.Font.MeasureString(title).Y + (int)(150 * GUI.Scale);
|
||||
}
|
||||
|
||||
var background = new GUIFrame(new RectTransform(new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight), GUI.Canvas, Anchor.Center), style: "GUIBackgroundBlocker");
|
||||
|
||||
var infoBlock = new GUIFrame(new RectTransform(new Point(width, height), background.RectTransform, anchor));
|
||||
infoBlock.Flash(GUI.Style.Green);
|
||||
infoBlock.Flash(GUIStyle.Green);
|
||||
|
||||
var infoContent = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), infoBlock.RectTransform, Anchor.Center))
|
||||
{
|
||||
@@ -528,20 +459,12 @@ namespace Barotrauma.Tutorials
|
||||
if (title.Length > 0)
|
||||
{
|
||||
var titleBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContent.RectTransform),
|
||||
title, font: GUI.LargeFont, textAlignment: Alignment.Center, textColor: new Color(253, 174, 0));
|
||||
title, font: GUIStyle.LargeFont, textAlignment: Alignment.Center, textColor: new Color(253, 174, 0));
|
||||
titleBlock.RectTransform.IsFixedSize = true;
|
||||
}
|
||||
|
||||
List<RichTextData> richTextData = RichTextData.GetRichTextData(" " + text, out text);
|
||||
GUITextBlock textBlock;
|
||||
if (richTextData == null)
|
||||
{
|
||||
textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContent.RectTransform), text, wrap: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContent.RectTransform), richTextData, text, wrap: true);
|
||||
}
|
||||
text = RichString.Rich(text);
|
||||
GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContent.RectTransform), text, wrap: true);
|
||||
|
||||
textBlock.RectTransform.IsFixedSize = true;
|
||||
infoBoxClosedCallback = callback;
|
||||
@@ -589,22 +512,26 @@ namespace Barotrauma.Tutorials
|
||||
#endregion
|
||||
|
||||
#region Video
|
||||
protected void LoadVideo(TutorialSegment segment)
|
||||
protected void LoadVideo(Segment segment)
|
||||
{
|
||||
if (videoPlayer == null) videoPlayer = new VideoPlayer();
|
||||
if (segment.ContentType != TutorialContentTypes.ManualVideo)
|
||||
if (segment.ContentType != TutorialContentType.ManualVideo)
|
||||
{
|
||||
videoPlayer.LoadContent(playableContentPath, new VideoPlayer.VideoSettings(segment.VideoContent), new VideoPlayer.TextSettings(segment.VideoContent), segment.Id, true, segment.Objective, StopCurrentContentSegment);
|
||||
videoPlayer.LoadContent(
|
||||
PlayableContentPath,
|
||||
new VideoPlayer.VideoSettings(segment.VideoContent.Value.File),
|
||||
new VideoPlayer.TextSettings(segment.VideoContent.Value.TextTag, segment.VideoContent.Value.Width),
|
||||
segment.Id, true, segment.Objective, StopCurrentContentSegment);
|
||||
}
|
||||
else
|
||||
{
|
||||
videoPlayer.LoadContent(playableContentPath, new VideoPlayer.VideoSettings(segment.VideoContent), null, segment.Id, true, string.Empty, null);
|
||||
videoPlayer.LoadContent(PlayableContentPath, new VideoPlayer.VideoSettings(segment.VideoContent.Value.File), null, segment.Id, true, string.Empty, null);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Highlights
|
||||
protected void HighlightInventorySlot(Inventory inventory, string identifier, Color color, float fadeInDuration, float fadeOutDuration, float scaleUpAmount)
|
||||
protected void HighlightInventorySlot(Inventory inventory, Identifier identifier, Color color, float fadeInDuration, float fadeOutDuration, float scaleUpAmount)
|
||||
{
|
||||
if (inventory.visualSlots == null) { return; }
|
||||
for (int i = 0; i < inventory.Capacity; i++)
|
||||
@@ -616,7 +543,7 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
}
|
||||
|
||||
protected void HighlightInventorySlotWithTag(Inventory inventory, string tag, Color color, float fadeInDuration, float fadeOutDuration, float scaleUpAmount)
|
||||
protected void HighlightInventorySlotWithTag(Inventory inventory, Identifier tag, Color color, float fadeInDuration, float fadeOutDuration, float scaleUpAmount)
|
||||
{
|
||||
if (inventory.visualSlots == null) { return; }
|
||||
for (int i = 0; i < inventory.Capacity; i++)
|
||||
|
||||
@@ -5,11 +5,6 @@ namespace Barotrauma
|
||||
class TutorialMode : GameMode
|
||||
{
|
||||
public Tutorial Tutorial;
|
||||
|
||||
public static void StartTutorial(Tutorial tutorial)
|
||||
{
|
||||
tutorial.Initialize();
|
||||
}
|
||||
|
||||
public TutorialMode(GameModePreset preset)
|
||||
: base(preset)
|
||||
@@ -20,7 +15,6 @@ namespace Barotrauma
|
||||
{
|
||||
base.Start();
|
||||
GameMain.GameSession.CrewManager = new CrewManager(true);
|
||||
Tutorial.Start();
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
//don't consider the items to belong in the outpost to prevent the stealing icon from showing
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
tabMenu?.OnClose();
|
||||
tabMenu = null;
|
||||
NetLobbyScreen.JobInfoFrame = null;
|
||||
}
|
||||
@@ -64,12 +65,12 @@ namespace Barotrauma
|
||||
GameMain.Instance.ResolutionChanged -= CreateTopLeftButtons;
|
||||
};
|
||||
int buttonHeight = GUI.IntScale(40);
|
||||
Vector2 buttonSpriteSize = GUI.Style.GetComponentStyle("CrewListToggleButton").GetDefaultSprite().size;
|
||||
Vector2 buttonSpriteSize = GUIStyle.GetComponentStyle("CrewListToggleButton").GetDefaultSprite().size;
|
||||
int buttonWidth = (int)((buttonHeight / buttonSpriteSize.Y) * buttonSpriteSize.X);
|
||||
Point buttonSize = new Point(buttonWidth, buttonHeight);
|
||||
crewListButton = new GUIButton(new RectTransform(buttonSize, parent: topLeftButtonGroup.RectTransform), style: "CrewListToggleButton")
|
||||
{
|
||||
ToolTip = TextManager.GetWithVariable("hudbutton.crewlist", "[key]", GameMain.Config.KeyBindText(InputType.CrewOrders)),
|
||||
ToolTip = TextManager.GetWithVariable("hudbutton.crewlist", "[key]", GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.CrewOrders)),
|
||||
OnClicked = (GUIButton btn, object userdata) =>
|
||||
{
|
||||
if (CrewManager == null) { return false; }
|
||||
@@ -79,7 +80,7 @@ namespace Barotrauma
|
||||
};
|
||||
commandButton = new GUIButton(new RectTransform(buttonSize, parent: topLeftButtonGroup.RectTransform), style: "CommandButton")
|
||||
{
|
||||
ToolTip = TextManager.GetWithVariable("hudbutton.commandinterface", "[key]", GameMain.Config.KeyBindText(InputType.Command)),
|
||||
ToolTip = TextManager.GetWithVariable("hudbutton.commandinterface", "[key]", GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Command)),
|
||||
OnClicked = (button, userData) =>
|
||||
{
|
||||
if (CrewManager == null) { return false; }
|
||||
@@ -89,7 +90,7 @@ namespace Barotrauma
|
||||
};
|
||||
tabMenuButton = new GUIButton(new RectTransform(buttonSize, parent: topLeftButtonGroup.RectTransform), style: "TabMenuButton")
|
||||
{
|
||||
ToolTip = TextManager.GetWithVariable("hudbutton.tabmenu", "[key]", GameMain.Config.KeyBindText(InputType.InfoTab)),
|
||||
ToolTip = TextManager.GetWithVariable("hudbutton.tabmenu", "[key]", GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.InfoTab)),
|
||||
OnClicked = (button, userData) => ToggleTabMenu()
|
||||
};
|
||||
|
||||
@@ -190,7 +191,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
tabMenu.Update();
|
||||
tabMenu.Update(deltaTime);
|
||||
if ((PlayerInput.KeyHit(InputType.InfoTab) || PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape)) &&
|
||||
!(GUI.KeyboardDispatcher.Subscriber is GUITextBox))
|
||||
{
|
||||
|
||||
@@ -13,14 +13,14 @@ namespace Barotrauma
|
||||
{
|
||||
private const string HintManagerFile = "hintmanager.xml";
|
||||
|
||||
public static bool Enabled => GameMain.Config != null && !GameMain.Config.DisableInGameHints;
|
||||
private static HashSet<string> HintIdentifiers { get; set; }
|
||||
private static Dictionary<string, HashSet<string>> HintTags { get; } = new Dictionary<string, HashSet<string>>();
|
||||
private static Dictionary<string, (string identifier, string option)> HintOrders { get; } = new Dictionary<string, (string orderIdentifier, string orderOption)>();
|
||||
public static bool Enabled => !GameSettings.CurrentConfig.DisableInGameHints;
|
||||
private static HashSet<Identifier> HintIdentifiers { get; set; }
|
||||
private static Dictionary<Identifier, HashSet<Identifier>> HintTags { get; } = new Dictionary<Identifier, HashSet<Identifier>>();
|
||||
private static Dictionary<Identifier, (Identifier identifier, Identifier option)> HintOrders { get; } = new Dictionary<Identifier, (Identifier orderIdentifier, Identifier orderOption)>();
|
||||
/// <summary>
|
||||
/// Hints that have already been shown this round and shouldn't be shown shown again until the next round
|
||||
/// </summary>
|
||||
private static HashSet<string> HintsIgnoredThisRound { get; } = new HashSet<string>();
|
||||
private static HashSet<Identifier> HintsIgnoredThisRound { get; } = new HashSet<Identifier>();
|
||||
private static GUIMessageBox ActiveHintMessageBox { get; set; }
|
||||
private static Action OnUpdate { get; set; }
|
||||
private static double TimeStoppedInteracting { get; set; }
|
||||
@@ -43,10 +43,10 @@ namespace Barotrauma
|
||||
var doc = XMLExtensions.TryLoadXml(HintManagerFile);
|
||||
if (doc?.Root != null)
|
||||
{
|
||||
HintIdentifiers = new HashSet<string>();
|
||||
HintIdentifiers = new HashSet<Identifier>();
|
||||
foreach (var element in doc.Root.Elements())
|
||||
{
|
||||
GetHintsRecursive(element, element.Name.ToString());
|
||||
GetHintsRecursive(element, element.NameAsIdentifier());
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -59,18 +59,18 @@ namespace Barotrauma
|
||||
DebugConsole.ThrowError($"File \"{HintManagerFile}\" is missing - cannot initialize the HintManager!");
|
||||
}
|
||||
|
||||
static void GetHintsRecursive(XElement element, string identifier)
|
||||
static void GetHintsRecursive(XElement element, Identifier identifier)
|
||||
{
|
||||
if (!element.HasElements)
|
||||
{
|
||||
HintIdentifiers.Add(identifier);
|
||||
if (element.GetAttributeStringArray("tags", null, convertToLowerInvariant: true) is string[] tags)
|
||||
if (element.GetAttributeIdentifierArray("tags", null) is Identifier[] tags)
|
||||
{
|
||||
HintTags.TryAdd(identifier, tags.ToHashSet());
|
||||
}
|
||||
if (element.GetAttributeString("order", null) is string orderIdentifier && !string.IsNullOrEmpty(orderIdentifier))
|
||||
if (element.GetAttributeIdentifier("order", Identifier.Empty) is Identifier orderIdentifier && orderIdentifier != Identifier.Empty)
|
||||
{
|
||||
string orderOption = element.GetAttributeString("orderoption", "");
|
||||
Identifier orderOption = element.GetAttributeIdentifier("orderoption", Identifier.Empty);
|
||||
HintOrders.Add(identifier, (orderIdentifier, orderOption));
|
||||
}
|
||||
return;
|
||||
@@ -82,14 +82,14 @@ namespace Barotrauma
|
||||
}
|
||||
foreach (var childElement in element.Elements())
|
||||
{
|
||||
GetHintsRecursive(childElement, $"{identifier}.{childElement.Name}");
|
||||
GetHintsRecursive(childElement, $"{identifier}.{childElement.Name}".ToIdentifier());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Update()
|
||||
{
|
||||
if (HintIdentifiers == null || GameMain.Config.DisableInGameHints) { return; }
|
||||
if (HintIdentifiers == null || GameSettings.CurrentConfig.DisableInGameHints) { return; }
|
||||
if (GameMain.GameSession == null || !GameMain.GameSession.IsRunning) { return; }
|
||||
|
||||
if (ActiveHintMessageBox != null)
|
||||
@@ -137,7 +137,7 @@ namespace Barotrauma
|
||||
// onstartedinteracting.brokenitem
|
||||
if (item.Repairables.Any(r => r.IsBelowRepairThreshold))
|
||||
{
|
||||
if (DisplayHint($"{hintIdentifierBase}.brokenitem")) { return; }
|
||||
if (DisplayHint($"{hintIdentifierBase}.brokenitem".ToIdentifier())) { return; }
|
||||
}
|
||||
|
||||
// Don't display other item-related hints if the repair interface is displayed
|
||||
@@ -147,22 +147,25 @@ namespace Barotrauma
|
||||
if (item.Submarine?.Info?.Type == SubmarineType.Outpost &&
|
||||
item.ContainedItems.Any(i => !i.AllowStealing))
|
||||
{
|
||||
if (DisplayHint($"{hintIdentifierBase}.lootingisstealing")) { return; }
|
||||
if (DisplayHint($"{hintIdentifierBase}.lootingisstealing".ToIdentifier())) { return; }
|
||||
}
|
||||
|
||||
// onstartedinteracting.turretperiscope
|
||||
if (item.HasTag("periscope") &&
|
||||
item.GetConnectedComponents<Turret>().FirstOrDefault(t => t.Item.HasTag("turret")) is Turret)
|
||||
{
|
||||
if (DisplayHint($"{hintIdentifierBase}.turretperiscope",
|
||||
variableTags: new string[] { "[shootkey]", "[deselectkey]", },
|
||||
variableValues: new string[] { GameMain.Config.KeyBindText(InputType.Shoot), GameMain.Config.KeyBindText(InputType.Deselect) }))
|
||||
if (DisplayHint($"{hintIdentifierBase}.turretperiscope".ToIdentifier(),
|
||||
variables: new[]
|
||||
{
|
||||
("[shootkey]".ToIdentifier(), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Shoot)),
|
||||
("[deselectkey]".ToIdentifier(), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Deselect))
|
||||
}))
|
||||
{ return; }
|
||||
}
|
||||
|
||||
// onstartedinteracting.item...
|
||||
hintIdentifierBase += ".item";
|
||||
foreach (string hintIdentifier in HintIdentifiers)
|
||||
foreach (Identifier hintIdentifier in HintIdentifiers)
|
||||
{
|
||||
if (!hintIdentifier.StartsWith(hintIdentifierBase)) { continue; }
|
||||
if (!HintTags.TryGetValue(hintIdentifier, out var hintTags)) { continue; }
|
||||
@@ -180,7 +183,7 @@ namespace Barotrauma
|
||||
Character.Controlled.SelectedConstruction.OwnInventory?.AllItems is IEnumerable<Item> containedItems &&
|
||||
containedItems.Count(i => i.HasTag("reactorfuel")) > 1)
|
||||
{
|
||||
if (DisplayHint("onisinteracting.reactorwithextrarods")) { return; }
|
||||
if (DisplayHint("onisinteracting.reactorwithextrarods".ToIdentifier())) { return; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,11 +236,11 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
if (!GameMain.GameSession.GameMode.IsSinglePlayer &&
|
||||
GameMain.Config.VoiceSetting == GameSettings.VoiceMode.Disabled)
|
||||
GameSettings.CurrentConfig.Audio.VoiceSetting == VoiceMode.Disabled)
|
||||
{
|
||||
DisplayHint("onroundstarted.voipdisabled", onUpdate: () =>
|
||||
DisplayHint("onroundstarted.voipdisabled".ToIdentifier(), onUpdate: () =>
|
||||
{
|
||||
if (GameMain.Config.VoiceSetting == GameSettings.VoiceMode.Disabled) { return; }
|
||||
if (GameSettings.CurrentConfig.Audio.VoiceSetting == VoiceMode.Disabled) { return; }
|
||||
ActiveHintMessageBox.Close();
|
||||
});
|
||||
}
|
||||
@@ -271,7 +274,7 @@ namespace Barotrauma
|
||||
if (spottedCharacter == null || spottedCharacter.Removed || spottedCharacter.IsDead) { return; }
|
||||
if (Character.Controlled.SelectedConstruction != sonar) { return; }
|
||||
if (HumanAIController.IsFriendly(Character.Controlled, spottedCharacter)) { return; }
|
||||
DisplayHint("onsonarspottedenemy");
|
||||
DisplayHint("onsonarspottedenemy".ToIdentifier());
|
||||
}
|
||||
|
||||
public static void OnAfflictionDisplayed(Character character, List<Affliction> displayedAfflictions)
|
||||
@@ -285,9 +288,8 @@ namespace Barotrauma
|
||||
if (affliction.Prefab == AfflictionPrefab.OxygenLow) { continue; }
|
||||
if (affliction.Prefab == AfflictionPrefab.RadiationSickness && (GameMain.GameSession.Map?.Radiation?.IsEntityRadiated(character) ?? false)) { continue; }
|
||||
if (affliction.Strength < affliction.Prefab.ShowIconThreshold) { continue; }
|
||||
DisplayHint("onafflictiondisplayed",
|
||||
variableTags: new string[1] { "[key]" },
|
||||
variableValues: new string[1] { GameMain.Config.KeyBindText(InputType.Health) },
|
||||
DisplayHint("onafflictiondisplayed".ToIdentifier(),
|
||||
variables: new[] { ("[key]".ToIdentifier(), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Health)) },
|
||||
icon: affliction.Prefab.Icon,
|
||||
iconColor: CharacterHealth.GetAfflictionIconColor(affliction),
|
||||
onUpdate: () =>
|
||||
@@ -308,12 +310,11 @@ namespace Barotrauma
|
||||
if (TimeStoppedInteracting + 1 > Timing.TotalTime) { return; }
|
||||
if (GUI.MouseOn != null) { return; }
|
||||
if (Character.Controlled.Inventory?.visualSlots != null && Character.Controlled.Inventory.visualSlots.Any(s => s.InteractRect.Contains(PlayerInput.MousePosition))) { return; }
|
||||
string hintIdentifier = "onshootwithoutaiming";
|
||||
Identifier hintIdentifier = "onshootwithoutaiming".ToIdentifier();
|
||||
if (!HintTags.TryGetValue(hintIdentifier, out var tags)) { return; }
|
||||
if (!item.HasTag(tags)) { return; }
|
||||
DisplayHint(hintIdentifier,
|
||||
variableTags: new string[1] { "[key]" },
|
||||
variableValues: new string[1] { GameMain.Config.KeyBindText(InputType.Aim) },
|
||||
variables: new[] { ("[key]".ToIdentifier(), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Aim)) },
|
||||
onUpdate: () =>
|
||||
{
|
||||
if (character.SelectedConstruction == null && GUI.MouseOn == null && PlayerInput.KeyDown(InputType.Aim))
|
||||
@@ -328,21 +329,21 @@ namespace Barotrauma
|
||||
if (!CanDisplayHints()) { return; }
|
||||
if (character != Character.Controlled) { return; }
|
||||
if (door == null || door.Stuck < 20.0f) { return; }
|
||||
DisplayHint("onweldingdoor");
|
||||
DisplayHint("onweldingdoor".ToIdentifier());
|
||||
}
|
||||
|
||||
public static void OnTryOpenStuckDoor(Character character)
|
||||
{
|
||||
if (!CanDisplayHints()) { return; }
|
||||
if (character != Character.Controlled) { return; }
|
||||
DisplayHint("ontryopenstuckdoor");
|
||||
DisplayHint("ontryopenstuckdoor".ToIdentifier());
|
||||
}
|
||||
|
||||
public static void OnShowCampaignInterface(CampaignMode.InteractionType interactionType)
|
||||
{
|
||||
if (!CanDisplayHints()) { return; }
|
||||
if (interactionType == CampaignMode.InteractionType.None) { return; }
|
||||
string hintIdentifier = $"onshowcampaigninterface.{interactionType.ToString().ToLowerInvariant()}";
|
||||
Identifier hintIdentifier = $"onshowcampaigninterface.{interactionType}".ToIdentifier();
|
||||
DisplayHint(hintIdentifier, onUpdate: () =>
|
||||
{
|
||||
|
||||
@@ -359,7 +360,7 @@ namespace Barotrauma
|
||||
{
|
||||
IgnoreReminder("commandinterface");
|
||||
if (!CanDisplayHints()) { return; }
|
||||
DisplayHint("onshowcommandinterface", onUpdate: () =>
|
||||
DisplayHint("onshowcommandinterface".ToIdentifier(), onUpdate: () =>
|
||||
{
|
||||
if (CrewManager.IsCommandInterfaceOpen) { return; }
|
||||
ActiveHintMessageBox.Close();
|
||||
@@ -370,7 +371,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (!CanDisplayHints()) { return; }
|
||||
if (CharacterHealth.OpenHealthWindow == null) { return; }
|
||||
DisplayHint("onshowhealthinterface", onUpdate: () =>
|
||||
DisplayHint("onshowhealthinterface".ToIdentifier(), onUpdate: () =>
|
||||
{
|
||||
if (CharacterHealth.OpenHealthWindow != null) { return; }
|
||||
ActiveHintMessageBox.Close();
|
||||
@@ -387,7 +388,7 @@ namespace Barotrauma
|
||||
if (!CanDisplayHints()) { return; }
|
||||
if (character != Character.Controlled) { return; }
|
||||
if (item == null || item.AllowStealing || !item.StolenDuringRound) { return; }
|
||||
DisplayHint("onstoleitem", onUpdate: () =>
|
||||
DisplayHint("onstoleitem".ToIdentifier(), onUpdate: () =>
|
||||
{
|
||||
if (item == null || item.Removed || item.GetRootInventoryOwner() != character)
|
||||
{
|
||||
@@ -400,7 +401,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (!CanDisplayHints()) { return; }
|
||||
if (character != Character.Controlled || !character.LockHands) { return; }
|
||||
DisplayHint("onhandcuffed", onUpdate: () =>
|
||||
DisplayHint("onhandcuffed".ToIdentifier(), onUpdate: () =>
|
||||
{
|
||||
if (character != null && !character.Removed && character.LockHands) { return; }
|
||||
ActiveHintMessageBox.Close();
|
||||
@@ -413,7 +414,7 @@ namespace Barotrauma
|
||||
if (reactor == null) { return; }
|
||||
if (reactor.Item.Submarine?.Info?.Type != SubmarineType.Player || reactor.Item.Submarine.TeamID != Character.Controlled.TeamID) { return; }
|
||||
if (!HasValidJob("engineer")) { return; }
|
||||
DisplayHint("onreactoroutoffuel", onUpdate: () =>
|
||||
DisplayHint("onreactoroutoffuel".ToIdentifier(), onUpdate: () =>
|
||||
{
|
||||
if (reactor?.Item != null && !reactor.Item.Removed && reactor.AvailableFuel < 1) { return; }
|
||||
ActiveHintMessageBox.Close();
|
||||
@@ -424,13 +425,13 @@ namespace Barotrauma
|
||||
{
|
||||
if (!CanDisplayHints()) { return; }
|
||||
if (transitionType == CampaignMode.TransitionType.None) { return; }
|
||||
DisplayHint($"onavailabletransition.{transitionType.ToString().ToLowerInvariant()}");
|
||||
DisplayHint($"onavailabletransition.{transitionType}".ToIdentifier());
|
||||
}
|
||||
|
||||
public static void OnShowSubInventory(Item item)
|
||||
{
|
||||
if (item?.Prefab == null) { return; }
|
||||
if (item.Prefab.Identifier.Equals("toolbelt", StringComparison.OrdinalIgnoreCase))
|
||||
if (item.Prefab.Identifier == "toolbelt")
|
||||
{
|
||||
IgnoreReminder("toolbelt");
|
||||
}
|
||||
@@ -447,7 +448,7 @@ namespace Barotrauma
|
||||
if (character != Character.Controlled) { return; }
|
||||
if (character.IsDead) { return; }
|
||||
if (character.CharacterHealth != null && character.Vitality < character.CharacterHealth.MinVitality) { return; }
|
||||
DisplayHint("oncharacterunconscious");
|
||||
DisplayHint("oncharacterunconscious".ToIdentifier());
|
||||
}
|
||||
|
||||
public static void OnCharacterKilled(Character character)
|
||||
@@ -457,21 +458,21 @@ namespace Barotrauma
|
||||
if (GameMain.IsMultiplayer) { return; }
|
||||
if (GameMain.GameSession?.CrewManager == null) { return; }
|
||||
if (GameMain.GameSession.CrewManager.GetCharacters().None(c => !c.IsDead)) { return; }
|
||||
DisplayHint("oncharacterkilled");
|
||||
DisplayHint("oncharacterkilled".ToIdentifier());
|
||||
}
|
||||
|
||||
private static void OnStartedControlling()
|
||||
{
|
||||
if (Level.IsLoadedOutpost) { return; }
|
||||
if (Character.Controlled?.Info?.Job?.Prefab == null) { return; }
|
||||
string hintIdentifier = $"onstartedcontrolling.job.{Character.Controlled.Info.Job.Prefab.Identifier}";
|
||||
Identifier hintIdentifier = $"onstartedcontrolling.job.{Character.Controlled.Info.Job.Prefab.Identifier}".ToIdentifier();
|
||||
DisplayHint(hintIdentifier,
|
||||
icon: Character.Controlled.Info.Job.Prefab.Icon,
|
||||
iconColor: Character.Controlled.Info.Job.Prefab.UIColor,
|
||||
onDisplay: () =>
|
||||
{
|
||||
if (!HintOrders.TryGetValue(hintIdentifier, out var orderInfo)) { return; }
|
||||
var orderPrefab = Order.GetPrefab(orderInfo.identifier);
|
||||
var orderPrefab = OrderPrefab.Prefabs[orderInfo.identifier];
|
||||
if (orderPrefab == null) { return; }
|
||||
Item targetEntity = null;
|
||||
ItemComponent targetItem = null;
|
||||
@@ -481,8 +482,8 @@ namespace Barotrauma
|
||||
if (targetEntity == null) { return; }
|
||||
targetItem = orderPrefab.GetTargetItemComponent(targetEntity);
|
||||
}
|
||||
var order = new Order(orderPrefab, targetEntity as Entity, targetItem, orderGiver: Character.Controlled);
|
||||
GameMain.GameSession?.CrewManager?.SetCharacterOrder(Character.Controlled, order, orderInfo.option, CharacterInfo.HighestManualOrderPriority, Character.Controlled);
|
||||
var order = new Order(orderPrefab, orderInfo.option, targetEntity, targetItem, orderGiver: Character.Controlled).WithManualPriority(CharacterInfo.HighestManualOrderPriority);
|
||||
GameMain.GameSession.CrewManager.SetCharacterOrder(Character.Controlled, order);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -498,7 +499,7 @@ namespace Barotrauma
|
||||
if (!steering.SteeringPath.Finished && steering.SteeringPath.NextNode != null) { return; }
|
||||
if (steering.LevelStartSelected && (Level.Loaded.StartOutpost == null || !steering.Item.Submarine.AtStartExit)) { return; }
|
||||
if (steering.LevelEndSelected && (Level.Loaded.EndOutpost == null || !steering.Item.Submarine.AtEndExit)) { return; }
|
||||
DisplayHint("onautopilotreachedoutpost");
|
||||
DisplayHint("onautopilotreachedoutpost".ToIdentifier());
|
||||
}
|
||||
|
||||
public static void OnStatusEffectApplied(ItemComponent component, ActionType actionType, Character character)
|
||||
@@ -507,7 +508,7 @@ namespace Barotrauma
|
||||
if (character != Character.Controlled) { return; }
|
||||
// Could make this more generic if there will ever be any other status effect related hints
|
||||
if (!(component is Repairable) || actionType != ActionType.OnFailure) { return; }
|
||||
DisplayHint("onrepairfailed");
|
||||
DisplayHint("onrepairfailed".ToIdentifier());
|
||||
}
|
||||
|
||||
public static void OnActiveOrderAdded(Order order)
|
||||
@@ -519,7 +520,7 @@ namespace Barotrauma
|
||||
order.TargetEntity is Hull h &&
|
||||
h.Submarine?.TeamID == Character.Controlled.TeamID)
|
||||
{
|
||||
DisplayHint("onballastflorainfected");
|
||||
DisplayHint("onballastflorainfected".ToIdentifier());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -529,7 +530,7 @@ namespace Barotrauma
|
||||
var divingGear = Character.Controlled.GetEquippedItem("diving", InvSlotType.OuterClothes);
|
||||
if (divingGear?.OwnInventory == null) { return; }
|
||||
if (divingGear.GetContainedItemConditionPercentage() > 0.0f) { return; }
|
||||
DisplayHint("ondivinggearoutofoxygen", onUpdate: () =>
|
||||
DisplayHint("ondivinggearoutofoxygen".ToIdentifier(), onUpdate: () =>
|
||||
{
|
||||
if (divingGear == null || divingGear.Removed ||
|
||||
Character.Controlled == null || !Character.Controlled.HasEquippedItem(divingGear) ||
|
||||
@@ -546,7 +547,7 @@ namespace Barotrauma
|
||||
if (Character.Controlled.CurrentHull == null) { return; }
|
||||
if (HumanAIController.IsBallastFloraNoticeable(Character.Controlled, Character.Controlled.CurrentHull))
|
||||
{
|
||||
if (IsOnFriendlySub() && DisplayHint("onballastflorainfected")) { return; }
|
||||
if (IsOnFriendlySub() && DisplayHint("onballastflorainfected".ToIdentifier())) { return; }
|
||||
}
|
||||
foreach (var gap in Character.Controlled.CurrentHull.ConnectedGaps)
|
||||
{
|
||||
@@ -556,7 +557,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (!IsWearingDivingSuit()) { continue; }
|
||||
if (Character.Controlled.IsProtectedFromPressure()) { continue; }
|
||||
if (DisplayHint("divingsuitwarning", extendTextTag: false)) { return; }
|
||||
if (DisplayHint("divingsuitwarning".ToIdentifier(), extendTextTag: false)) { return; }
|
||||
continue;
|
||||
}
|
||||
foreach (var me in gap.linkedTo)
|
||||
@@ -565,8 +566,8 @@ namespace Barotrauma
|
||||
if (!(me is Hull adjacentHull)) { continue; }
|
||||
if (!IsOnFriendlySub()) { continue; }
|
||||
if (IsWearingDivingSuit()) { continue; }
|
||||
if (adjacentHull.LethalPressure > 5.0f && DisplayHint("onadjacenthull.highpressure")) { return; }
|
||||
if (adjacentHull.WaterPercentage > 75 && !BallastHulls.Contains(adjacentHull) && DisplayHint("onadjacenthull.highwaterpercentage")) { return; }
|
||||
if (adjacentHull.LethalPressure > 5.0f && DisplayHint("onadjacenthull.highpressure".ToIdentifier())) { return; }
|
||||
if (adjacentHull.WaterPercentage > 75 && !BallastHulls.Contains(adjacentHull) && DisplayHint("onadjacenthull.highwaterpercentage".ToIdentifier())) { return; }
|
||||
}
|
||||
|
||||
static bool IsWearingDivingSuit() => Character.Controlled.GetEquippedItem("deepdiving", InvSlotType.OuterClothes) is Item;
|
||||
@@ -586,7 +587,7 @@ namespace Barotrauma
|
||||
|
||||
if (GameMain.GameSession.GameMode.IsSinglePlayer)
|
||||
{
|
||||
if (DisplayHint($"{hintIdentifierBase}.characterchange"))
|
||||
if (DisplayHint($"{hintIdentifierBase}.characterchange".ToIdentifier()))
|
||||
{
|
||||
TimeReminderLastDisplayed = GameMain.GameScreen.GameTime;
|
||||
return;
|
||||
@@ -595,9 +596,8 @@ namespace Barotrauma
|
||||
|
||||
if (Level.Loaded.Type != LevelData.LevelType.Outpost)
|
||||
{
|
||||
if (DisplayHint($"{hintIdentifierBase}.commandinterface",
|
||||
variableTags: new string[] { "[commandkey]" },
|
||||
variableValues: new string[] { GameMain.Config.KeyBindText(InputType.Command) },
|
||||
if (DisplayHint($"{hintIdentifierBase}.commandinterface".ToIdentifier(),
|
||||
variables: new[] { ("[commandkey]".ToIdentifier(), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Command)) },
|
||||
onUpdate: () =>
|
||||
{
|
||||
if (!CrewManager.IsCommandInterfaceOpen) { return; }
|
||||
@@ -609,9 +609,8 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (DisplayHint($"{hintIdentifierBase}.tabmenu",
|
||||
variableTags: new string[] { "[infotabkey]" },
|
||||
variableValues: new string[] { GameMain.Config.KeyBindText(InputType.InfoTab) },
|
||||
if (DisplayHint($"{hintIdentifierBase}.tabmenu".ToIdentifier(),
|
||||
variables: new[] { ("[infotabkey]".ToIdentifier(), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.InfoTab)) },
|
||||
onUpdate: () =>
|
||||
{
|
||||
if (!GameSession.IsTabMenuOpen) { return; }
|
||||
@@ -624,7 +623,7 @@ namespace Barotrauma
|
||||
|
||||
if (Character.Controlled.Inventory?.GetItemInLimbSlot(InvSlotType.Bag)?.Prefab?.Identifier == "toolbelt")
|
||||
{
|
||||
if (DisplayHint($"{hintIdentifierBase}.toolbelt"))
|
||||
if (DisplayHint($"{hintIdentifierBase}.toolbelt".ToIdentifier()))
|
||||
{
|
||||
TimeReminderLastDisplayed = GameMain.GameScreen.GameTime;
|
||||
return;
|
||||
@@ -632,25 +631,25 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private static bool DisplayHint(string hintIdentifier, bool extendTextTag = true, string[] variableTags = null, string[] variableValues = null, Sprite icon = null, Color? iconColor = null, Action onDisplay = null, Action onUpdate = null)
|
||||
private static bool DisplayHint(Identifier hintIdentifier, bool extendTextTag = true, (Identifier Tag, LocalizedString Value)[] variables = null, Sprite icon = null, Color? iconColor = null, Action onDisplay = null, Action onUpdate = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(hintIdentifier)) { return false; }
|
||||
if (hintIdentifier == Identifier.Empty) { return false; }
|
||||
if (!HintIdentifiers.Contains(hintIdentifier)) { return false; }
|
||||
if (GameMain.Config.IgnoredHints.Contains(hintIdentifier)) { return false; }
|
||||
if (IgnoredHints.Instance.Contains(hintIdentifier)) { return false; }
|
||||
if (HintsIgnoredThisRound.Contains(hintIdentifier)) { return false; }
|
||||
|
||||
string text;
|
||||
string textTag = extendTextTag ? $"hint.{hintIdentifier}" : hintIdentifier;
|
||||
if (variableTags != null && variableTags != null && variableTags.Length > 0 && variableTags.Length == variableValues.Length)
|
||||
LocalizedString text;
|
||||
Identifier textTag = extendTextTag ? $"hint.{hintIdentifier}".ToIdentifier() : hintIdentifier;
|
||||
if (variables != null && variables.Length > 0)
|
||||
{
|
||||
text = TextManager.GetWithVariables(textTag, variableTags, variableValues, returnNull: true);
|
||||
text = TextManager.GetWithVariables(textTag, variables);
|
||||
}
|
||||
else
|
||||
{
|
||||
text = TextManager.Get(textTag, returnNull: true);
|
||||
text = TextManager.Get(textTag);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(text))
|
||||
if (text.IsNullOrEmpty())
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError($"No hint text found for text tag \"{textTag}\"");
|
||||
@@ -668,20 +667,20 @@ namespace Barotrauma
|
||||
ActiveHintMessageBox.InnerFrame.Flash(color: iconColor ?? Color.Orange, flashDuration: 0.75f);
|
||||
onDisplay?.Invoke();
|
||||
|
||||
GameAnalyticsManager.AddDesignEvent($"HintManager:{GameMain.GameSession?.GameMode?.Preset?.Identifier ?? "none"}:HintDisplayed:{hintIdentifier}");
|
||||
GameAnalyticsManager.AddDesignEvent($"HintManager:{GameMain.GameSession?.GameMode?.Preset?.Identifier ?? "none".ToIdentifier()}:HintDisplayed:{hintIdentifier}");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool OnDontShowAgain(GUITickBox tickBox)
|
||||
{
|
||||
IgnoreHint((string)tickBox.UserData, ignore: tickBox.Selected);
|
||||
IgnoreHint((Identifier)tickBox.UserData, ignore: tickBox.Selected);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void IgnoreHint(string hintIdentifier, bool ignore = true)
|
||||
private static void IgnoreHint(Identifier hintIdentifier, bool ignore = true)
|
||||
{
|
||||
if (string.IsNullOrEmpty(hintIdentifier)) { return; }
|
||||
if (hintIdentifier.IsEmpty) { return; }
|
||||
if (!HintIdentifiers.Contains(hintIdentifier))
|
||||
{
|
||||
#if DEBUG
|
||||
@@ -691,29 +690,32 @@ namespace Barotrauma
|
||||
}
|
||||
if (ignore)
|
||||
{
|
||||
GameMain.Config.IgnoredHints.Add(hintIdentifier);
|
||||
IgnoredHints.Instance.Add(hintIdentifier);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.Config.IgnoredHints.Remove(hintIdentifier);
|
||||
IgnoredHints.Instance.Remove(hintIdentifier);
|
||||
}
|
||||
}
|
||||
|
||||
private static void IgnoreReminder(string reminderIdentifier)
|
||||
{
|
||||
HintsIgnoredThisRound.Add($"reminder.{reminderIdentifier}");
|
||||
HintsIgnoredThisRound.Add($"reminder.{reminderIdentifier}".ToIdentifier());
|
||||
}
|
||||
|
||||
public static bool OnDisableHints(GUITickBox tickBox)
|
||||
{
|
||||
GameMain.Config.DisableInGameHints = tickBox.Selected;
|
||||
return GameMain.Config.SaveNewPlayerConfig();
|
||||
var config = GameSettings.CurrentConfig;
|
||||
config.DisableInGameHints = tickBox.Selected;
|
||||
GameSettings.SetCurrentConfig(config);
|
||||
GameSettings.SaveCurrentConfig();
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool CanDisplayHints(bool requireGameScreen = true, bool requireControllingCharacter = true)
|
||||
{
|
||||
if (HintIdentifiers == null) { return false; }
|
||||
if (GameMain.Config.DisableInGameHints) { return false; }
|
||||
if (GameSettings.CurrentConfig.DisableInGameHints) { return false; }
|
||||
if (ActiveHintMessageBox != null) { return false; }
|
||||
if (requireControllingCharacter && Character.Controlled == null) { return false; }
|
||||
var gameMode = GameMain.GameSession?.GameMode;
|
||||
|
||||
@@ -181,6 +181,11 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMoneyChanged(WalletChangedEvent e)
|
||||
{
|
||||
if (e.Wallet.IsOwnWallet) { OnUpdate?.Invoke(); }
|
||||
}
|
||||
|
||||
// if you have more than 5000 ping there are probably more important things to worry about but hey just in case
|
||||
private static DateTimeOffset GetTimeout() => DateTimeOffset.Now.AddSeconds(5).AddMilliseconds(GetPing());
|
||||
|
||||
@@ -241,6 +246,7 @@ namespace Barotrauma
|
||||
private void HealRequestReceived(IReadMessage inc)
|
||||
{
|
||||
NetHealRequest request = INetSerializableStruct.Read<NetHealRequest>(inc);
|
||||
|
||||
if (request.Result == HealRequestResult.Success)
|
||||
{
|
||||
HealAllPending(force: true);
|
||||
|
||||
@@ -9,16 +9,18 @@ namespace Barotrauma
|
||||
{
|
||||
internal partial class ReadyCheck
|
||||
{
|
||||
private static string readyCheckBody(string name) => string.IsNullOrWhiteSpace(name) ? TextManager.Get("readycheck.serverbody") : TextManager.GetWithVariable("readycheck.body", "[player]", name);
|
||||
private static LocalizedString readyCheckBody(string name) => string.IsNullOrWhiteSpace(name) ? TextManager.Get("readycheck.serverbody") : TextManager.GetWithVariable("readycheck.body", "[player]", name);
|
||||
|
||||
private static string readyCheckStatus(int ready, int total) => TextManager.GetWithVariables("readycheck.readycount", new[] { "[ready]", "[total]" }, new[] { ready.ToString(), total.ToString() });
|
||||
private static string readyCheckPleaseWait(int seconds) => TextManager.GetWithVariable("readycheck.pleasewait", "[seconds]", seconds.ToString());
|
||||
private static LocalizedString readyCheckStatus(int ready, int total) => TextManager.GetWithVariables("readycheck.readycount",
|
||||
("[ready]", ready.ToString()),
|
||||
("[total]", total.ToString()));
|
||||
private static LocalizedString readyCheckPleaseWait(int seconds) => TextManager.GetWithVariable("readycheck.pleasewait", "[seconds]", seconds.ToString());
|
||||
|
||||
private static readonly string readyCheckHeader = TextManager.Get("ReadyCheck.Title");
|
||||
private static readonly LocalizedString readyCheckHeader = TextManager.Get("ReadyCheck.Title");
|
||||
|
||||
private static readonly string noButton = TextManager.Get("No"),
|
||||
yesButton = TextManager.Get("Yes"),
|
||||
closeButton = TextManager.Get("Close");
|
||||
private static readonly LocalizedString noButton = TextManager.Get("No"),
|
||||
yesButton = TextManager.Get("Yes"),
|
||||
closeButton = TextManager.Get("Close");
|
||||
|
||||
private const string TimerData = "Timer",
|
||||
PromptData = "ReadyCheck",
|
||||
@@ -42,7 +44,7 @@ namespace Barotrauma
|
||||
msgBox = new GUIMessageBox(readyCheckHeader, readyCheckBody(author), new[] { yesButton, noButton }, relativeSize, minSize, type: GUIMessageBox.Type.Vote) { UserData = PromptData, Draggable = true };
|
||||
|
||||
GUILayoutGroup contentLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.125f), msgBox.Content.RectTransform), childAnchor: Anchor.Center);
|
||||
new GUIProgressBar(new RectTransform(new Vector2(0.8f, 1f), contentLayout.RectTransform), time / endTime, GUI.Style.Orange) { UserData = TimerData };
|
||||
new GUIProgressBar(new RectTransform(new Vector2(0.8f, 1f), contentLayout.RectTransform), time / endTime, GUIStyle.Orange) { UserData = TimerData };
|
||||
|
||||
// Yes
|
||||
msgBox.Buttons[0].OnClicked = delegate
|
||||
@@ -222,7 +224,7 @@ namespace Barotrauma
|
||||
|
||||
int readyCount = Clients.Count(pair => pair.Value == ReadyStatus.Yes);
|
||||
int totalCount = Clients.Count;
|
||||
GameMain.Client.AddChatMessage(ChatMessage.Create(string.Empty, readyCheckStatus(readyCount, totalCount), ChatMessageType.Server, null));
|
||||
GameMain.Client.AddChatMessage(ChatMessage.Create(string.Empty, readyCheckStatus(readyCount, totalCount).Value, ChatMessageType.Server, null));
|
||||
}
|
||||
|
||||
private void UpdateState(byte id, ReadyStatus status)
|
||||
@@ -256,7 +258,7 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
|
||||
image.ApplyStyle(GUI.Style.GetComponentStyle(style));
|
||||
image.ApplyStyle(GUIStyle.GetComponentStyle(style));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
@@ -15,7 +16,6 @@ namespace Barotrauma
|
||||
|
||||
private int jobColumnWidth, characterColumnWidth, statusColumnWidth;
|
||||
|
||||
private readonly SubmarineInfo sub;
|
||||
private readonly List<Mission> selectedMissions;
|
||||
private readonly Location startLocation, endLocation;
|
||||
|
||||
@@ -30,11 +30,8 @@ namespace Barotrauma
|
||||
|
||||
public GUIComponent Frame { get; private set; }
|
||||
|
||||
|
||||
|
||||
public RoundSummary(SubmarineInfo sub, GameMode gameMode, IEnumerable<Mission> selectedMissions, Location startLocation, Location endLocation)
|
||||
public RoundSummary(GameMode gameMode, IEnumerable<Mission> selectedMissions, Location startLocation, Location endLocation)
|
||||
{
|
||||
this.sub = sub;
|
||||
this.gameMode = gameMode;
|
||||
this.selectedMissions = selectedMissions.ToList();
|
||||
this.startLocation = startLocation;
|
||||
@@ -59,7 +56,7 @@ namespace Barotrauma
|
||||
|
||||
if (!singleplayer)
|
||||
{
|
||||
SoundPlayer.OverrideMusicType = gameOver ? "crewdead" : "endround";
|
||||
SoundPlayer.OverrideMusicType = (gameOver ? "crewdead" : "endround").ToIdentifier();
|
||||
SoundPlayer.OverrideMusicDuration = 18.0f;
|
||||
}
|
||||
|
||||
@@ -84,7 +81,7 @@ namespace Barotrauma
|
||||
};
|
||||
|
||||
var crewHeader = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), crewContent.RectTransform),
|
||||
TextManager.Get("crew"), textAlignment: Alignment.TopLeft, font: GUI.SubHeadingFont);
|
||||
TextManager.Get("crew"), textAlignment: Alignment.TopLeft, font: GUIStyle.SubHeadingFont);
|
||||
crewHeader.RectTransform.MinSize = new Point(0, GUI.IntScale(crewHeader.Rect.Height * 2.0f));
|
||||
|
||||
CreateCrewList(crewContent, gameSession.CrewManager.GetCharacterInfos().Where(c => c.TeamID != CharacterTeamType.Team2));
|
||||
@@ -101,19 +98,19 @@ namespace Barotrauma
|
||||
Stretch = true
|
||||
};
|
||||
var crewHeader2 = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), crewContent2.RectTransform),
|
||||
CombatMission.GetTeamName(CharacterTeamType.Team2), textAlignment: Alignment.TopLeft, font: GUI.SubHeadingFont);
|
||||
CombatMission.GetTeamName(CharacterTeamType.Team2), textAlignment: Alignment.TopLeft, font: GUIStyle.SubHeadingFont);
|
||||
crewHeader2.RectTransform.MinSize = new Point(0, GUI.IntScale(crewHeader2.Rect.Height * 2.0f));
|
||||
CreateCrewList(crewContent2, gameSession.CrewManager.GetCharacterInfos().Where(c => c.TeamID == CharacterTeamType.Team2));
|
||||
}
|
||||
|
||||
//header -------------------------------------------------------------------------------
|
||||
|
||||
string headerText = GetHeaderText(gameOver, transitionType);
|
||||
LocalizedString headerText = GetHeaderText(gameOver, transitionType);
|
||||
GUITextBlock headerTextBlock = null;
|
||||
if (!string.IsNullOrEmpty(headerText))
|
||||
if (!headerText.IsNullOrEmpty())
|
||||
{
|
||||
headerTextBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), crewFrame.RectTransform, Anchor.TopLeft, Pivot.BottomLeft),
|
||||
headerText, textAlignment: Alignment.BottomLeft, font: GUI.LargeFont, wrap: true);
|
||||
headerText, textAlignment: Alignment.BottomLeft, font: GUIStyle.LargeFont, wrap: true);
|
||||
}
|
||||
|
||||
//traitor panel -------------------------------------------------------------------------------
|
||||
@@ -130,14 +127,14 @@ namespace Barotrauma
|
||||
};
|
||||
|
||||
var traitorHeader = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), traitorContent.RectTransform),
|
||||
TextManager.Get("traitors"), font: GUI.SubHeadingFont);
|
||||
TextManager.Get("traitors"), font: GUIStyle.SubHeadingFont);
|
||||
traitorHeader.RectTransform.MinSize = new Point(0, GUI.IntScale(traitorHeader.Rect.Height * 2.0f));
|
||||
|
||||
GUIListBox listBox = CreateCrewList(traitorContent, traitorResults.SelectMany(tr => tr.Characters.Select(c => c.Info)));
|
||||
|
||||
foreach (var traitorResult in traitorResults)
|
||||
{
|
||||
var traitorMission = TraitorMissionPrefab.List.Find(t => t.Identifier == traitorResult.MissionIdentifier);
|
||||
var traitorMission = TraitorMissionPrefab.Prefabs.Find(t => t.Identifier == traitorResult.MissionIdentifier);
|
||||
if (traitorMission == null) { continue; }
|
||||
|
||||
//spacing
|
||||
@@ -154,8 +151,8 @@ namespace Barotrauma
|
||||
Color = traitorMission.IconColor
|
||||
};
|
||||
|
||||
string traitorMessage = TextManager.GetServerMessage(traitorResult.EndMessage);
|
||||
if (!string.IsNullOrEmpty(traitorMessage))
|
||||
LocalizedString traitorMessage = TextManager.GetServerMessage(traitorResult.EndMessage);
|
||||
if (!traitorMessage.IsNullOrEmpty())
|
||||
{
|
||||
var textContent = new GUILayoutGroup(new RectTransform(Vector2.One, traitorResultHorizontal.RectTransform))
|
||||
{
|
||||
@@ -164,10 +161,10 @@ namespace Barotrauma
|
||||
|
||||
var traitorStatusText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), textContent.RectTransform),
|
||||
TextManager.Get(traitorResult.Success ? "missioncompleted" : "missionfailed"),
|
||||
textColor: traitorResult.Success ? GUI.Style.Green : GUI.Style.Red, font: GUI.SubHeadingFont);
|
||||
textColor: traitorResult.Success ? GUIStyle.Green : GUIStyle.Red, font: GUIStyle.SubHeadingFont);
|
||||
|
||||
var traitorMissionInfo = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), textContent.RectTransform),
|
||||
traitorMessage, font: GUI.SmallFont, wrap: true);
|
||||
traitorMessage, font: GUIStyle.SmallFont, wrap: true);
|
||||
|
||||
traitorResultHorizontal.Recalculate();
|
||||
|
||||
@@ -196,7 +193,7 @@ namespace Barotrauma
|
||||
};
|
||||
|
||||
var reputationHeader = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), reputationContent.RectTransform),
|
||||
TextManager.Get("reputation"), textAlignment: Alignment.TopLeft, font: GUI.SubHeadingFont);
|
||||
TextManager.Get("reputation"), textAlignment: Alignment.TopLeft, font: GUIStyle.SubHeadingFont);
|
||||
reputationHeader.RectTransform.MinSize = new Point(0, GUI.IntScale(reputationHeader.Rect.Height * 2.0f));
|
||||
|
||||
CreateReputationInfoPanel(reputationContent, campaignMode);
|
||||
@@ -233,7 +230,7 @@ namespace Barotrauma
|
||||
if (missionsToDisplay.Any())
|
||||
{
|
||||
var missionHeader = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionContent.RectTransform),
|
||||
TextManager.Get(missionsToDisplay.Count > 1 ? "Missions" : "Mission"), textAlignment: Alignment.TopLeft, font: GUI.SubHeadingFont);
|
||||
TextManager.Get(missionsToDisplay.Count > 1 ? "Missions" : "Mission"), textAlignment: Alignment.TopLeft, font: GUIStyle.SubHeadingFont);
|
||||
missionHeader.RectTransform.MinSize = new Point(0, (int)(missionHeader.Rect.Height * 1.2f));
|
||||
}
|
||||
|
||||
@@ -271,7 +268,7 @@ namespace Barotrauma
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
string missionMessage =
|
||||
LocalizedString missionMessage =
|
||||
selectedMissions.Contains(displayedMission) ?
|
||||
displayedMission.Completed ? displayedMission.SuccessMessage : displayedMission.FailureMessage :
|
||||
displayedMission.Description;
|
||||
@@ -293,7 +290,7 @@ namespace Barotrauma
|
||||
};
|
||||
missionContentHorizontal.Recalculate();
|
||||
var missionNameTextBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform),
|
||||
displayedMission.Name, font: GUI.SubHeadingFont);
|
||||
displayedMission.Name, font: GUIStyle.SubHeadingFont);
|
||||
if (displayedMission.Difficulty.HasValue)
|
||||
{
|
||||
var groupSize = missionNameTextBlock.Rect.Size;
|
||||
@@ -314,12 +311,21 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
var missionDescription = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform),
|
||||
missionMessage, wrap: true, parseRichText: true);
|
||||
RichString.Rich(missionMessage), wrap: true);
|
||||
int reward = displayedMission.GetReward(Submarine.MainSub);
|
||||
if (selectedMissions.Contains(displayedMission) && displayedMission.Completed && reward > 0)
|
||||
{
|
||||
string rewardText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", reward));
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), displayedMission.GetMissionRewardText(Submarine.MainSub), parseRichText: true);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), RichString.Rich(displayedMission.GetMissionRewardText(Submarine.MainSub)));
|
||||
if (GameMain.IsMultiplayer && Character.Controlled is { } controlled)
|
||||
{
|
||||
var (share, percentage, _) = Mission.GetRewardShare(controlled.Wallet.RewardDistribution, GameSession.GetSessionCrewCharacters(CharacterType.Player).Where(c => c != controlled), Option<int>.Some(reward));
|
||||
if (share > 0)
|
||||
{
|
||||
string shareFormatted = string.Format(CultureInfo.InvariantCulture, "{0:N0}", share);
|
||||
RichString yourShareString = RichString.Rich(TextManager.GetWithVariables("crewwallet.missionreward.get", ("[money]", $"{shareFormatted}"), ("[share]", $"{percentage}")));
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), yourShareString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (displayedMission != missionsToDisplay.Last())
|
||||
@@ -346,7 +352,7 @@ namespace Barotrauma
|
||||
GUIImage missionIcon = new GUIImage(new RectTransform(new Point((int)(missionContentHorizontal.Rect.Height * 0.7f)), missionContentHorizontal.RectTransform), style: "NoMissionIcon", scaleToFit: true);
|
||||
missionIcon.RectTransform.MinSize = new Point((int)(missionContentHorizontal.Rect.Height * 0.7f));
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionContentHorizontal.RectTransform),
|
||||
TextManager.Get("nomission"), font: GUI.LargeFont);
|
||||
TextManager.Get("nomission"), font: GUIStyle.LargeFont);
|
||||
}
|
||||
|
||||
/*missionContentHorizontal.Recalculate();
|
||||
@@ -397,7 +403,7 @@ namespace Barotrauma
|
||||
|
||||
if (startLocation.Type.HasOutpost && startLocation.Reputation != null)
|
||||
{
|
||||
var iconStyle = GUI.Style.GetComponentStyle("LocationReputationIcon");
|
||||
var iconStyle = GUIStyle.GetComponentStyle("LocationReputationIcon");
|
||||
var locationFrame = CreateReputationElement(
|
||||
reputationList.Content,
|
||||
startLocation.Name,
|
||||
@@ -407,7 +413,7 @@ namespace Barotrauma
|
||||
CreatePathUnlockElement(locationFrame, null, startLocation);
|
||||
}
|
||||
|
||||
foreach (Faction faction in campaignMode.Factions)
|
||||
foreach (Faction faction in campaignMode.Factions.OrderBy(f => f.Prefab.MenuOrder).ThenBy(f => f.Prefab.Name))
|
||||
{
|
||||
float initialReputation = faction.Reputation.Value;
|
||||
if (initialFactionReputations.ContainsKey(faction))
|
||||
@@ -452,8 +458,8 @@ namespace Barotrauma
|
||||
|
||||
var gateLocation = connection.Locations[0].IsGateBetweenBiomes ? connection.Locations[0] : connection.Locations[1];
|
||||
var unlockEvent =
|
||||
EventSet.PrefabList.Find(ep => ep.UnlockPathEvent && ep.BiomeIdentifier == gateLocation.LevelData.Biome.Identifier) ??
|
||||
EventSet.PrefabList.Find(ep => ep.UnlockPathEvent && string.IsNullOrEmpty(ep.BiomeIdentifier));
|
||||
EventPrefab.Prefabs.FirstOrDefault(ep => ep.UnlockPathEvent && ep.BiomeIdentifier == gateLocation.LevelData.Biome.Identifier) ??
|
||||
EventPrefab.Prefabs.FirstOrDefault(ep => ep.UnlockPathEvent && ep.BiomeIdentifier == Identifier.Empty);
|
||||
|
||||
if (unlockEvent == null) { continue; }
|
||||
if (string.IsNullOrEmpty(unlockEvent.UnlockPathFaction) || unlockEvent.UnlockPathFaction.Equals("location", StringComparison.OrdinalIgnoreCase))
|
||||
@@ -462,7 +468,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
if (faction == null || !faction.Prefab.Identifier.Equals(unlockEvent.UnlockPathFaction, StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||
if (faction == null || faction.Prefab.Identifier != unlockEvent.UnlockPathFaction) { continue; }
|
||||
}
|
||||
|
||||
if (unlockEvent != null)
|
||||
@@ -471,20 +477,20 @@ namespace Barotrauma
|
||||
Faction unlockFaction = null;
|
||||
if (!string.IsNullOrEmpty(unlockEvent.UnlockPathFaction))
|
||||
{
|
||||
unlockFaction = GameMain.GameSession.Campaign.Factions.Find(f => f.Prefab.Identifier.Equals(unlockEvent.UnlockPathFaction, StringComparison.OrdinalIgnoreCase));
|
||||
unlockFaction = GameMain.GameSession.Campaign.Factions.Find(f => f.Prefab.Identifier == unlockEvent.UnlockPathFaction);
|
||||
unlockReputation = unlockFaction?.Reputation;
|
||||
}
|
||||
float normalizedUnlockReputation = MathUtils.InverseLerp(unlockReputation.MinReputation, unlockReputation.MaxReputation, unlockEvent.UnlockPathReputation);
|
||||
string unlockText = TextManager.GetWithVariables(
|
||||
RichString unlockText = RichString.Rich(TextManager.GetWithVariables(
|
||||
"lockedpathreputationrequirement",
|
||||
new string[] { "[reputation]", "[biomename]" },
|
||||
new string[] { Reputation.GetFormattedReputationText(normalizedUnlockReputation, unlockEvent.UnlockPathReputation, addColorTags: true), $"‖color:gui.orange‖{connection.LevelData.Biome.DisplayName}‖end‖" });
|
||||
("[reputation]", Reputation.GetFormattedReputationText(normalizedUnlockReputation, unlockEvent.UnlockPathReputation, addColorTags: true)),
|
||||
("[biomename]", $"‖color:gui.orange‖{connection.LevelData.Biome.DisplayName}‖end‖")));
|
||||
var unlockInfoPanel = new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.0f), reputationFrame.RectTransform, Anchor.BottomCenter) { MinSize = new Point(0, GUI.IntScale(30)), AbsoluteOffset = new Point(0, GUI.IntScale(3)) },
|
||||
unlockText, style: "GUIButtonRound", textAlignment: Alignment.Center, textColor: GUI.Style.TextColor, parseRichText: true);
|
||||
unlockText, style: "GUIButtonRound", textAlignment: Alignment.Center, textColor: GUIStyle.TextColorNormal);
|
||||
unlockInfoPanel.Color = Color.Lerp(unlockInfoPanel.Color, Color.Black, 0.8f);
|
||||
if (unlockInfoPanel.TextSize.X > unlockInfoPanel.Rect.Width * 0.7f)
|
||||
{
|
||||
unlockInfoPanel.Font = GUI.SmallFont;
|
||||
unlockInfoPanel.Font = GUIStyle.SmallFont;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -492,7 +498,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private string GetHeaderText(bool gameOver, CampaignMode.TransitionType transitionType)
|
||||
private LocalizedString GetHeaderText(bool gameOver, CampaignMode.TransitionType transitionType)
|
||||
{
|
||||
string locationName = Submarine.MainSub.AtEndExit ? endLocation?.Name : startLocation?.Name;
|
||||
|
||||
@@ -539,14 +545,14 @@ namespace Barotrauma
|
||||
locationName = "[UNKNOWN]";
|
||||
}
|
||||
|
||||
string subName = string.Empty;
|
||||
LocalizedString subName = string.Empty;
|
||||
SubmarineInfo currentOrPending = SubmarineSelection.CurrentOrPendingSubmarine();
|
||||
if (currentOrPending != null)
|
||||
{
|
||||
subName = currentOrPending.DisplayName;
|
||||
}
|
||||
|
||||
return TextManager.GetWithVariables(textTag, new string[2] { "[sub]", "[location]" }, new string[2] { subName, locationName });
|
||||
return TextManager.GetWithVariables(textTag, ("[sub]", subName), ("[location]", locationName));
|
||||
}
|
||||
|
||||
private GUIListBox CreateCrewList(GUIComponent parent, IEnumerable<CharacterInfo> characterInfos)
|
||||
@@ -566,9 +572,9 @@ namespace Barotrauma
|
||||
characterButton.RectTransform.RelativeSize = new Vector2(characterColumnWidthPercentage * sizeMultiplier, 1f);
|
||||
statusButton.RectTransform.RelativeSize = new Vector2(statusColumnWidthPercentage * sizeMultiplier, 1f);
|
||||
|
||||
jobButton.TextBlock.Font = characterButton.TextBlock.Font = statusButton.TextBlock.Font = GUI.HotkeyFont;
|
||||
jobButton.TextBlock.Font = characterButton.TextBlock.Font = statusButton.TextBlock.Font = GUIStyle.HotkeyFont;
|
||||
jobButton.CanBeFocused = characterButton.CanBeFocused = statusButton.CanBeFocused = false;
|
||||
jobButton.TextBlock.ForceUpperCase = characterButton.TextBlock.ForceUpperCase = statusButton.ForceUpperCase = true;
|
||||
jobButton.TextBlock.ForceUpperCase = characterButton.TextBlock.ForceUpperCase = statusButton.ForceUpperCase = ForceUpperCase.Yes;
|
||||
|
||||
jobColumnWidth = jobButton.Rect.Width;
|
||||
characterColumnWidth = characterButton.Rect.Width;
|
||||
@@ -615,10 +621,10 @@ namespace Barotrauma
|
||||
};
|
||||
|
||||
GUITextBlock characterNameBlock = new GUITextBlock(new RectTransform(new Point(characterColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform),
|
||||
ToolBox.LimitString(characterInfo.Name, GUI.Font, characterColumnWidth), textAlignment: Alignment.Center, textColor: characterInfo.Job.Prefab.UIColor);
|
||||
ToolBox.LimitString(characterInfo.Name, GUIStyle.Font, characterColumnWidth), textAlignment: Alignment.Center, textColor: characterInfo.Job.Prefab.UIColor);
|
||||
|
||||
string statusText = TextManager.Get("StatusOK");
|
||||
Color statusColor = GUI.Style.Green;
|
||||
LocalizedString statusText = TextManager.Get("StatusOK");
|
||||
Color statusColor = GUIStyle.Green;
|
||||
|
||||
Character character = characterInfo.Character;
|
||||
if (character == null || character.IsDead)
|
||||
@@ -626,7 +632,7 @@ namespace Barotrauma
|
||||
if (character == null && characterInfo.IsNewHire && characterInfo.CauseOfDeath == null)
|
||||
{
|
||||
statusText = TextManager.Get("CampaignCrew.NewHire");
|
||||
statusColor = GUI.Style.Blue;
|
||||
statusColor = GUIStyle.Blue;
|
||||
}
|
||||
else if (characterInfo.CauseOfDeath == null)
|
||||
{
|
||||
@@ -637,9 +643,9 @@ namespace Barotrauma
|
||||
{
|
||||
string errorMsg = "Character \"[name]\" had an invalid cause of death (the type of the cause of death was Affliction, but affliction was not specified).";
|
||||
DebugConsole.ThrowError(errorMsg.Replace("[name]", characterInfo.Name));
|
||||
GameAnalyticsManager.AddErrorEventOnce("RoundSummary:InvalidCauseOfDeath", GameAnalyticsManager.ErrorSeverity.Error, errorMsg.Replace("[name]", characterInfo.SpeciesName));
|
||||
GameAnalyticsManager.AddErrorEventOnce("RoundSummary:InvalidCauseOfDeath", GameAnalyticsManager.ErrorSeverity.Error, errorMsg.Replace("[name]", characterInfo.SpeciesName.Value));
|
||||
statusText = TextManager.Get("CauseOfDeathDescription.Unknown");
|
||||
statusColor = GUI.Style.Red;
|
||||
statusColor = GUIStyle.Red;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -664,12 +670,12 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
GUITextBlock statusBlock = new GUITextBlock(new RectTransform(new Point(statusColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform),
|
||||
ToolBox.LimitString(statusText, GUI.Font, characterColumnWidth), textAlignment: Alignment.Center, textColor: statusColor);
|
||||
ToolBox.LimitString(statusText.Value, GUIStyle.Font, characterColumnWidth), textAlignment: Alignment.Center, textColor: statusColor);
|
||||
}
|
||||
|
||||
private GUIFrame CreateReputationElement(GUIComponent parent,
|
||||
string name, float reputation, float normalizedReputation, float initialReputation,
|
||||
string shortDescription, string fullDescription, Sprite icon, Sprite backgroundPortrait, Color iconColor)
|
||||
LocalizedString name, float reputation, float normalizedReputation, float initialReputation,
|
||||
LocalizedString shortDescription, LocalizedString fullDescription, Sprite icon, Sprite backgroundPortrait, Color iconColor)
|
||||
{
|
||||
var factionFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.1f), parent.RectTransform), style: null);
|
||||
|
||||
@@ -704,7 +710,7 @@ namespace Barotrauma
|
||||
factionInfoHorizontal.Recalculate();
|
||||
|
||||
var header = new GUITextBlock(new RectTransform(new Point(factionTextContent.Rect.Width, GUI.IntScale(40)), factionTextContent.RectTransform),
|
||||
name, font: GUI.SubHeadingFont)
|
||||
name, font: GUIStyle.SubHeadingFont)
|
||||
{
|
||||
Padding = Vector4.Zero,
|
||||
UserData = "header"
|
||||
@@ -723,34 +729,34 @@ namespace Barotrauma
|
||||
new GUICustomComponent(new RectTransform(new Vector2(0.8f, 1.0f), sliderHolder.RectTransform),
|
||||
onDraw: (sb, customComponent) => DrawReputationBar(sb, customComponent.Rect, normalizedReputation));
|
||||
|
||||
string reputationText = Reputation.GetFormattedReputationText(normalizedReputation, reputation, addColorTags: true);
|
||||
LocalizedString reputationText = Reputation.GetFormattedReputationText(normalizedReputation, reputation, addColorTags: true);
|
||||
int reputationChange = (int)Math.Round(reputation - initialReputation);
|
||||
if (Math.Abs(reputationChange) > 0)
|
||||
{
|
||||
string changeText = $"{(reputationChange > 0 ? "+" : "") + reputationChange}";
|
||||
string colorStr = XMLExtensions.ColorToString(reputationChange > 0 ? GUI.Style.Green : GUI.Style.Red);
|
||||
var rtData = RichTextData.GetRichTextData($"{reputationText} (‖color:{colorStr}‖{changeText}‖color:end‖)", out string sanitizedText);
|
||||
string colorStr = XMLExtensions.ToStringHex(reputationChange > 0 ? GUIStyle.Green : GUIStyle.Red);
|
||||
var richText = RichString.Rich($"{reputationText} (‖color:{colorStr}‖{changeText}‖color:end‖)");
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), sliderHolder.RectTransform),
|
||||
rtData, sanitizedText,
|
||||
textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont);
|
||||
richText,
|
||||
textAlignment: Alignment.CenterLeft, font: GUIStyle.SubHeadingFont);
|
||||
}
|
||||
else
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), sliderHolder.RectTransform),
|
||||
reputationText,
|
||||
textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont, parseRichText: true);
|
||||
RichString.Rich(reputationText),
|
||||
textAlignment: Alignment.CenterLeft, font: GUIStyle.SubHeadingFont);
|
||||
}
|
||||
|
||||
//spacing
|
||||
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.0f), factionTextContent.RectTransform) { MinSize = new Point(0, GUI.IntScale(5)) }, style: null);
|
||||
|
||||
var factionDescription = new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.6f), factionTextContent.RectTransform),
|
||||
shortDescription, font: GUI.SmallFont, wrap: true)
|
||||
shortDescription, font: GUIStyle.SmallFont, wrap: true)
|
||||
{
|
||||
UserData = "description",
|
||||
Padding = Vector4.Zero
|
||||
};
|
||||
if (shortDescription != fullDescription && !string.IsNullOrEmpty(fullDescription))
|
||||
if (shortDescription != fullDescription && !fullDescription.IsNullOrEmpty())
|
||||
{
|
||||
factionDescription.ToolTip = fullDescription;
|
||||
}
|
||||
@@ -771,16 +777,16 @@ namespace Barotrauma
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
GUI.DrawRectangle(sb, new Rectangle(rect.X + (segmentWidth * i), rect.Y, segmentWidth, rect.Height), Reputation.GetReputationColor(i / 5.0f), isFilled: true);
|
||||
GUI.DrawRectangle(sb, new Rectangle(rect.X + (segmentWidth * i), rect.Y, segmentWidth, rect.Height), GUI.Style.ColorInventoryBackground, isFilled: false);
|
||||
GUI.DrawRectangle(sb, new Rectangle(rect.X + (segmentWidth * i), rect.Y, segmentWidth, rect.Height), GUIStyle.ColorInventoryBackground, isFilled: false);
|
||||
}
|
||||
GUI.DrawRectangle(sb, rect, GUI.Style.ColorInventoryBackground, isFilled: false);
|
||||
GUI.DrawRectangle(sb, rect, GUIStyle.ColorInventoryBackground, isFilled: false);
|
||||
|
||||
GUI.Arrow.Draw(sb, new Vector2(rect.X + rect.Width * normalizedReputation, rect.Y), GUI.Style.ColorInventoryBackground, scale: GUI.Scale, spriteEffect: SpriteEffects.FlipVertically);
|
||||
GUI.Arrow.Draw(sb, new Vector2(rect.X + rect.Width * normalizedReputation, rect.Y), GUI.Style.TextColor, scale: GUI.Scale * 0.8f, spriteEffect: SpriteEffects.FlipVertically);
|
||||
GUI.Arrow.Draw(sb, new Vector2(rect.X + rect.Width * normalizedReputation, rect.Y), GUIStyle.ColorInventoryBackground, scale: GUI.Scale, spriteEffect: SpriteEffects.FlipVertically);
|
||||
GUI.Arrow.Draw(sb, new Vector2(rect.X + rect.Width * normalizedReputation, rect.Y), GUIStyle.TextColorNormal, scale: GUI.Scale * 0.8f, spriteEffect: SpriteEffects.FlipVertically);
|
||||
|
||||
GUI.DrawString(sb, new Vector2(rect.X, rect.Bottom), "-100", GUI.Style.TextColor, font: GUI.SmallFont);
|
||||
Vector2 textSize = GUI.SmallFont.MeasureString("100");
|
||||
GUI.DrawString(sb, new Vector2(rect.Right - textSize.X, rect.Bottom), "100", GUI.Style.TextColor, font: GUI.SmallFont);
|
||||
GUI.DrawString(sb, new Vector2(rect.X, rect.Bottom), "-100", GUIStyle.TextColorNormal, font: GUIStyle.SmallFont);
|
||||
Vector2 textSize = GUIStyle.SmallFont.MeasureString("100");
|
||||
GUI.DrawString(sb, new Vector2(rect.Right - textSize.X, rect.Bottom), "100", GUIStyle.TextColorNormal, font: GUIStyle.SmallFont);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -109,7 +109,7 @@ namespace Barotrauma
|
||||
|
||||
indicatorGroup = new GUILayoutGroup(new RectTransform(Point.Zero, hideButton.RectTransform)) { IsHorizontal = false };
|
||||
indicatorGroup.ChildAnchor = Anchor.TopCenter;
|
||||
indicatorSpriteSize = GUI.Style.GetComponentStyle("EquipmentIndicatorDivingSuit").GetDefaultSprite().size;
|
||||
indicatorSpriteSize = GUIStyle.GetComponentStyle("EquipmentIndicatorDivingSuit").GetDefaultSprite().size;
|
||||
|
||||
indicators[0] = new GUIImage(new RectTransform(Point.Zero, indicatorGroup.RectTransform), "EquipmentIndicatorDivingSuit");
|
||||
indicators[1] = new GUIImage(new RectTransform(Point.Zero, indicatorGroup.RectTransform), "EquipmentIndicatorID");
|
||||
@@ -522,7 +522,7 @@ namespace Barotrauma
|
||||
|
||||
public override void Update(float deltaTime, Camera cam, bool isSubInventory = false)
|
||||
{
|
||||
if (!AccessibleWhenAlive && !character.IsDead)
|
||||
if (!AccessibleWhenAlive && !character.IsDead && !AccessibleByOwner)
|
||||
{
|
||||
syncItemsDelay = Math.Max(syncItemsDelay - deltaTime, 0.0f);
|
||||
return;
|
||||
@@ -814,21 +814,21 @@ namespace Barotrauma
|
||||
|
||||
if (conditionPercentage != -1)
|
||||
{
|
||||
indicators[i].Color = ToolBox.GradientLerp(conditionPercentage, GUI.Style.EquipmentIndicatorRunningOut, GUI.Style.EquipmentIndicatorEquipped);
|
||||
indicators[i].Color = ToolBox.GradientLerp(conditionPercentage, GUIStyle.EquipmentIndicatorRunningOut, GUIStyle.EquipmentIndicatorEquipped);
|
||||
}
|
||||
else
|
||||
{
|
||||
indicators[i].Color = GUI.Style.EquipmentIndicatorRunningOut;
|
||||
indicators[i].Color = GUIStyle.EquipmentIndicatorRunningOut;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
indicators[i].Color = GUI.Style.EquipmentIndicatorEquipped;
|
||||
indicators[i].Color = GUIStyle.EquipmentIndicatorEquipped;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
indicators[i].Color = GUI.Style.EquipmentIndicatorNotEquipped;
|
||||
indicators[i].Color = GUIStyle.EquipmentIndicatorNotEquipped;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -966,7 +966,7 @@ namespace Barotrauma
|
||||
}
|
||||
else if (character.HeldItems.Any(i =>
|
||||
i.OwnInventory != null &&
|
||||
(i.OwnInventory.CanBePut(item) || (i.OwnInventory.Capacity == 1 && i.OwnInventory.AllowSwappingContainedItems && i.OwnInventory.Container.CanBeContained(item)))))
|
||||
((i.OwnInventory.CanBePut(item) && allowInventorySwap) || (i.OwnInventory.Capacity == 1 && i.OwnInventory.AllowSwappingContainedItems && i.OwnInventory.Container.CanBeContained(item)))))
|
||||
{
|
||||
return QuickUseAction.PutToEquippedItem;
|
||||
}
|
||||
@@ -1007,7 +1007,7 @@ namespace Barotrauma
|
||||
var slot = invSlots[i];
|
||||
if (item.ParentInventory.GetItemAt(i) == item)
|
||||
{
|
||||
slot.ShowBorderHighlight(GUI.Style.Red, 0.1f, 0.4f);
|
||||
slot.ShowBorderHighlight(GUIStyle.Red, 0.1f, 0.4f);
|
||||
SoundPlayer.PlayUISound(GUISoundType.PickItem);
|
||||
break;
|
||||
}
|
||||
@@ -1033,7 +1033,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (GUIMessageBox.MessageBoxes.Any(mb => mb.UserData as string == "equipconfirmation")) { return; }
|
||||
var equipConfirmation = new GUIMessageBox(string.Empty, TextManager.Get(item.Prefab.EquipConfirmationText),
|
||||
new string[] { TextManager.Get("yes"), TextManager.Get("no") })
|
||||
new LocalizedString[] { TextManager.Get("yes"), TextManager.Get("no") })
|
||||
{
|
||||
UserData = "equipconfirmation"
|
||||
};
|
||||
@@ -1138,7 +1138,7 @@ namespace Barotrauma
|
||||
success = true;
|
||||
for (int j = 0; j < capacity; j++)
|
||||
{
|
||||
if (slots[j].Contains(heldItem)) { visualSlots[j].ShowBorderHighlight(GUI.Style.Green, 0.1f, 0.4f); }
|
||||
if (slots[j].Contains(heldItem)) { visualSlots[j].ShowBorderHighlight(GUIStyle.Green, 0.1f, 0.4f); }
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1150,7 +1150,7 @@ namespace Barotrauma
|
||||
{
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
if (slots[i].Contains(item)) { visualSlots[i].ShowBorderHighlight(GUI.Style.Green, 0.1f, 0.4f); }
|
||||
if (slots[i].Contains(item)) { visualSlots[i].ShowBorderHighlight(GUIStyle.Green, 0.1f, 0.4f); }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1163,7 +1163,7 @@ namespace Barotrauma
|
||||
|
||||
public void DrawOwn(SpriteBatch spriteBatch)
|
||||
{
|
||||
if (!AccessibleWhenAlive && !character.IsDead) { return; }
|
||||
if (!AccessibleWhenAlive && !character.IsDead && !AccessibleByOwner) { return; }
|
||||
if (capacity == 0) { return; }
|
||||
if (visualSlots == null) { CreateSlots(); }
|
||||
if (GameMain.GraphicsWidth != screenResolution.X ||
|
||||
@@ -1182,7 +1182,7 @@ namespace Barotrauma
|
||||
CalculateBackgroundFrame();
|
||||
GUI.DrawRectangle(spriteBatch, BackgroundFrame, Color.Black * 0.8f, true);
|
||||
GUI.DrawString(spriteBatch,
|
||||
new Vector2((int)(BackgroundFrame.Center.X - GUI.Font.MeasureString(character.Name).X / 2), (int)BackgroundFrame.Y + 5),
|
||||
new Vector2((int)(BackgroundFrame.Center.X - GUIStyle.Font.MeasureString(character.Name).X / 2), (int)BackgroundFrame.Y + 5),
|
||||
character.Name, Color.White * 0.9f);
|
||||
}
|
||||
|
||||
@@ -1218,7 +1218,7 @@ namespace Barotrauma
|
||||
if (LimbSlotIcons.ContainsKey(SlotTypes[i]))
|
||||
{
|
||||
var icon = LimbSlotIcons[SlotTypes[i]];
|
||||
icon.Draw(spriteBatch, visualSlots[i].Rect.Center.ToVector2() + visualSlots[i].DrawOffset, GUI.Style.EquipmentSlotIconColor, origin: icon.size / 2, scale: visualSlots[i].Rect.Width / icon.size.X);
|
||||
icon.Draw(spriteBatch, visualSlots[i].Rect.Center.ToVector2() + visualSlots[i].DrawOffset, GUIStyle.EquipmentSlotIconColor, origin: icon.size / 2, scale: visualSlots[i].Rect.Width / icon.size.X);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -1292,14 +1292,14 @@ namespace Barotrauma
|
||||
if (Locked)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, inventoryArea, new Color(30,30,30,100), isFilled: true);
|
||||
var lockIcon = GUI.Style.GetComponentStyle("LockIcon")?.GetDefaultSprite();
|
||||
var lockIcon = GUIStyle.GetComponentStyle("LockIcon")?.GetDefaultSprite();
|
||||
lockIcon?.Draw(spriteBatch, inventoryArea.Center.ToVector2(), scale: Math.Min(inventoryArea.Height / lockIcon.size.Y * 0.7f, 1.0f));
|
||||
if (inventoryArea.Contains(PlayerInput.MousePosition))
|
||||
{
|
||||
GUIComponent.DrawToolTip(spriteBatch, TextManager.Get("handcuffed"), new Rectangle(inventoryArea.Center - new Point(inventoryArea.Height / 2), new Point(inventoryArea.Height)));
|
||||
}
|
||||
}
|
||||
else if (highlightedQuickUseSlot != null && !string.IsNullOrEmpty(highlightedQuickUseSlot.QuickUseButtonToolTip))
|
||||
else if (highlightedQuickUseSlot != null && !highlightedQuickUseSlot.QuickUseButtonToolTip.IsNullOrEmpty())
|
||||
{
|
||||
GUIComponent.DrawToolTip(spriteBatch, highlightedQuickUseSlot.QuickUseButtonToolTip, highlightedQuickUseSlot.EquipButtonRect);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Barotrauma.Items.Components
|
||||
//openState when the vertices of the convex hull were last calculated
|
||||
private float lastConvexHullState;
|
||||
|
||||
[Serialize("1,1", false, description: "The scale of the shadow-casting area of the door (relative to the actual size of the door).")]
|
||||
[Serialize("1,1", IsPropertySaveable.No, description: "The scale of the shadow-casting area of the door (relative to the actual size of the door).")]
|
||||
public Vector2 ShadowScale
|
||||
{
|
||||
get;
|
||||
@@ -283,9 +283,9 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public override void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||
public override void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||
{
|
||||
base.ClientRead(type, msg, sendingTime);
|
||||
base.ClientEventRead(msg, sendingTime);
|
||||
|
||||
bool open = msg.ReadBoolean();
|
||||
bool broken = msg.ReadBoolean();
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||
{
|
||||
CurrPowerConsumption = powerConsumption;
|
||||
charging = true;
|
||||
|
||||
@@ -17,12 +17,12 @@ namespace Barotrauma.Items.Components
|
||||
case AreaShape.Rectangle:
|
||||
{
|
||||
RectangleF rect = GetAreaRectangle(SpawnAreaBounds, SpawnAreaOffset, draw: true);
|
||||
GUI.DrawRectangle(spriteBatch, rect.Location, rect.Size, GUI.Style.Red, isFilled: false, 0f, 4f);
|
||||
GUI.DrawRectangle(spriteBatch, rect.Location, rect.Size, GUIStyle.Red, isFilled: false, 0f, 4f);
|
||||
|
||||
if (MaximumAmountRangePadding > 0f)
|
||||
{
|
||||
rect.Inflate(MaximumAmountRangePadding, MaximumAmountRangePadding);
|
||||
GUI.DrawRectangle(spriteBatch, rect.Location, rect.Size, GUI.Style.Red, isFilled: false, 0f, 2f);
|
||||
GUI.DrawRectangle(spriteBatch, rect.Location, rect.Size, GUIStyle.Red, isFilled: false, 0f, 2f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -30,11 +30,11 @@ namespace Barotrauma.Items.Components
|
||||
Vector2 center = item.WorldPosition;
|
||||
center += SpawnAreaOffset;
|
||||
center.Y = -center.Y;
|
||||
spriteBatch.DrawCircle(center, SpawnAreaRadius, 32, GUI.Style.Red, thickness: 4f);
|
||||
spriteBatch.DrawCircle(center, SpawnAreaRadius, 32, GUIStyle.Red, thickness: 4f);
|
||||
|
||||
if (MaximumAmountRangePadding > 0f)
|
||||
{
|
||||
spriteBatch.DrawCircle(center, SpawnAreaRadius + MaximumAmountRangePadding, 32, GUI.Style.Red, thickness: 2f);
|
||||
spriteBatch.DrawCircle(center, SpawnAreaRadius + MaximumAmountRangePadding, 32, GUIStyle.Red, thickness: 2f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -46,14 +46,14 @@ namespace Barotrauma.Items.Components
|
||||
case AreaShape.Rectangle:
|
||||
{
|
||||
RectangleF rect = GetAreaRectangle(CrewAreaBounds, CrewAreaOffset, draw: true);
|
||||
GUI.DrawRectangle(spriteBatch, rect.Location, rect.Size, GUI.Style.Green, isFilled: false, 0f, 4f);
|
||||
GUI.DrawRectangle(spriteBatch, rect.Location, rect.Size, GUIStyle.Green, isFilled: false, 0f, 4f);
|
||||
break;
|
||||
}
|
||||
case AreaShape.Circle:
|
||||
Vector2 center = item.WorldPosition;
|
||||
center += CrewAreaOffset;
|
||||
center.Y = -center.Y;
|
||||
spriteBatch.DrawCircle(center, CrewAreaRadius, 32, GUI.Style.Green);
|
||||
spriteBatch.DrawCircle(center, CrewAreaRadius, 32, GUIStyle.Green);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,17 +6,17 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class GeneticMaterial : ItemComponent
|
||||
{
|
||||
[Serialize(0.0f, false)]
|
||||
[Serialize(0.0f, IsPropertySaveable.No)]
|
||||
public float TooltipValueMin { get; set; }
|
||||
|
||||
[Serialize(0.0f, false)]
|
||||
[Serialize(0.0f, IsPropertySaveable.No)]
|
||||
public float TooltipValueMax { get; set; }
|
||||
|
||||
public override void AddTooltipInfo(ref string name, ref string description)
|
||||
public override void AddTooltipInfo(ref LocalizedString name, ref LocalizedString description)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(materialName) && item.ContainedItems.Count() > 0)
|
||||
if (!materialName.IsNullOrEmpty() && item.ContainedItems.Count() > 0)
|
||||
{
|
||||
string mergedMaterialName = materialName;
|
||||
LocalizedString mergedMaterialName = materialName;
|
||||
foreach (Item containedItem in item.ContainedItems)
|
||||
{
|
||||
var containedMaterial = containedItem.GetComponent<GeneticMaterial>();
|
||||
@@ -31,30 +31,30 @@ namespace Barotrauma.Items.Components
|
||||
name = TextManager.GetWithVariable("entityname.taintedgeneticmaterial", "[geneticmaterialname]", name);
|
||||
}
|
||||
|
||||
if (TextManager.ContainsTag("entitydescription." + Item.prefab.Identifier))
|
||||
if (TextManager.ContainsTag("entitydescription." + Item.Prefab.Identifier))
|
||||
{
|
||||
int value = (int)MathHelper.Lerp(TooltipValueMin, TooltipValueMax, item.ConditionPercentage / 100.0f);
|
||||
description = TextManager.GetWithVariable("entitydescription." + Item.prefab.Identifier, "[value]", value.ToString());
|
||||
description = TextManager.GetWithVariable("entitydescription." + Item.Prefab.Identifier, "[value]", value.ToString());
|
||||
}
|
||||
foreach (Item containedItem in item.ContainedItems)
|
||||
{
|
||||
var containedGeneticMaterial = containedItem.GetComponent<GeneticMaterial>();
|
||||
if (containedGeneticMaterial == null) { continue; }
|
||||
string _ = string.Empty;
|
||||
string containedDescription = containedItem.Description;
|
||||
LocalizedString _ = string.Empty;
|
||||
LocalizedString containedDescription = containedItem.Description;
|
||||
containedGeneticMaterial.AddTooltipInfo(ref _, ref containedDescription);
|
||||
if (!string.IsNullOrEmpty(containedDescription))
|
||||
if (!containedDescription.IsNullOrEmpty())
|
||||
{
|
||||
description += '\n' + containedDescription;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ModifyDeconstructInfo(Deconstructor deconstructor, ref string buttonText, ref string infoText)
|
||||
public void ModifyDeconstructInfo(Deconstructor deconstructor, ref LocalizedString buttonText, ref LocalizedString infoText)
|
||||
{
|
||||
if (deconstructor.InputContainer.Inventory.AllItems.Count() == 2)
|
||||
{
|
||||
if (!deconstructor.InputContainer.Inventory.AllItems.All(it => it.prefab == item.prefab))
|
||||
if (!deconstructor.InputContainer.Inventory.AllItems.All(it => it.Prefab == item.Prefab))
|
||||
{
|
||||
buttonText = TextManager.Get("researchstation.combine");
|
||||
infoText = TextManager.Get("researchstation.combine.infotext");
|
||||
@@ -68,18 +68,18 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||
{
|
||||
Tainted = msg.ReadBoolean();
|
||||
if (Tainted)
|
||||
{
|
||||
uint selectedTaintedEffectId = msg.ReadUInt32();
|
||||
selectedTaintedEffect = AfflictionPrefab.Prefabs.Find(a => a.UIntIdentifier == selectedTaintedEffectId);
|
||||
selectedTaintedEffect = AfflictionPrefab.Prefabs.Find(a => a.UintIdentifier == selectedTaintedEffectId);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint selectedEffectId = msg.ReadUInt32();
|
||||
selectedEffect = AfflictionPrefab.Prefabs.Find(a => a.UIntIdentifier == selectedEffectId);
|
||||
selectedEffect = AfflictionPrefab.Prefabs.Find(a => a.UintIdentifier == selectedEffectId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
@@ -10,15 +11,15 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
internal class VineSprite
|
||||
{
|
||||
[Serialize("0,0,0,0", false)]
|
||||
[Serialize("0,0,0,0", IsPropertySaveable.No)]
|
||||
public Rectangle SourceRect { get; private set; }
|
||||
|
||||
[Serialize("0.5,0.5", false)]
|
||||
[Serialize("0.5,0.5", IsPropertySaveable.No)]
|
||||
public Vector2 Origin { get; private set; }
|
||||
|
||||
public Vector2 AbsoluteOrigin;
|
||||
|
||||
public VineSprite(XElement element)
|
||||
public VineSprite(ContentXElement element)
|
||||
{
|
||||
SerializableProperty.DeserializeProperties(this, element);
|
||||
AbsoluteOrigin = new Vector2(SourceRect.Width * Origin.X, SourceRect.Height * Origin.Y);
|
||||
@@ -109,28 +110,27 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
partial void LoadVines(XElement element)
|
||||
partial void LoadVines(ContentXElement element)
|
||||
{
|
||||
string? vineAtlasPath = element.GetAttributeString("vineatlas", null);
|
||||
string? decayAtlasPath = element.GetAttributeString("decayatlas", null);
|
||||
ContentPath vineAtlasPath = element.GetAttributeContentPath("vineatlas") ?? ContentPath.Empty;
|
||||
ContentPath decayAtlasPath = element.GetAttributeContentPath("decayatlas") ?? ContentPath.Empty;
|
||||
|
||||
if (vineAtlasPath != null)
|
||||
if (!vineAtlasPath.IsNullOrEmpty())
|
||||
{
|
||||
VineAtlas = new Sprite(vineAtlasPath, Rectangle.Empty);
|
||||
VineAtlas = new Sprite(vineAtlasPath.Value, Rectangle.Empty);
|
||||
}
|
||||
|
||||
if (decayAtlasPath != null)
|
||||
if (!decayAtlasPath.IsNullOrEmpty())
|
||||
{
|
||||
DecayAtlas = new Sprite(decayAtlasPath, Rectangle.Empty);
|
||||
DecayAtlas = new Sprite(decayAtlasPath.Value, Rectangle.Empty);
|
||||
}
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "vinesprite":
|
||||
var tileType = subElement.GetAttributeString("type", null);
|
||||
VineTileType type = Enum.Parse<VineTileType>(tileType);
|
||||
VineTileType type = subElement.GetAttributeEnum("type", VineTileType.Stem);
|
||||
VineSprites.Add(type, new VineSprite(subElement));
|
||||
break;
|
||||
case "flowersprite":
|
||||
@@ -145,18 +145,18 @@ namespace Barotrauma.Items.Components
|
||||
leafVariants = LeafSprites.Count;
|
||||
}
|
||||
|
||||
foreach (VineTileType type in Enum.GetValues(typeof(VineTileType)))
|
||||
foreach (VineTileType type in Enum.GetValues(typeof(VineTileType)).Cast<VineTileType>())
|
||||
{
|
||||
if (!VineSprites.ContainsKey(type))
|
||||
{
|
||||
DebugConsole.ThrowError($"Vine sprite missing from {item.prefab.Identifier}: {type}");
|
||||
DebugConsole.ThrowError($"Vine sprite missing from {item.Prefab.Identifier}: {type}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private readonly object mutex = new object();
|
||||
|
||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||
{
|
||||
Health = msg.ReadRangedSingle(0, MaxHealth, 8);
|
||||
int startOffset = msg.ReadRangedInteger(-1, MaximumVines);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user