(965c31410a) Unstable v0.10.4.0
This commit is contained in:
@@ -163,7 +163,8 @@ namespace Barotrauma
|
|||||||
position = Vector2.Zero;
|
position = Vector2.Zero;
|
||||||
|
|
||||||
CreateMatrices();
|
CreateMatrices();
|
||||||
GameMain.Instance.OnResolutionChanged += () => { CreateMatrices(); };
|
// TODO: Needs to unregister if ever destroy cameras.
|
||||||
|
GameMain.Instance.ResolutionChanged += CreateMatrices;
|
||||||
|
|
||||||
UpdateTransform(false);
|
UpdateTransform(false);
|
||||||
}
|
}
|
||||||
@@ -260,26 +261,29 @@ namespace Barotrauma
|
|||||||
if (targetPos == Vector2.Zero)
|
if (targetPos == Vector2.Zero)
|
||||||
{
|
{
|
||||||
Vector2 moveInput = Vector2.Zero;
|
Vector2 moveInput = Vector2.Zero;
|
||||||
if (allowMove && GUI.KeyboardDispatcher.Subscriber == null)
|
if (allowMove)
|
||||||
{
|
{
|
||||||
if (PlayerInput.KeyDown(Keys.LeftShift)) moveSpeed *= 2.0f;
|
if (GUI.KeyboardDispatcher.Subscriber == null)
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
velocity = Vector2.Lerp(velocity, moveInput, deltaTime * 10.0f);
|
|
||||||
moveCam = velocity * moveSpeed * deltaTime * 60.0f;
|
|
||||||
|
|
||||||
if (Screen.Selected == GameMain.GameScreen && FollowSub)
|
|
||||||
{
|
|
||||||
var closestSub = Submarine.FindClosest(WorldViewCenter);
|
|
||||||
if (closestSub != null)
|
|
||||||
{
|
{
|
||||||
moveCam += FarseerPhysics.ConvertUnits.ToDisplayUnits(closestSub.Velocity * deltaTime);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
velocity = Vector2.Lerp(velocity, moveInput, deltaTime * 10.0f);
|
||||||
|
moveCam = velocity * moveSpeed * deltaTime * 60.0f;
|
||||||
|
|
||||||
|
if (Screen.Selected == GameMain.GameScreen && FollowSub)
|
||||||
|
{
|
||||||
|
var closestSub = Submarine.FindClosest(WorldViewCenter);
|
||||||
|
if (closestSub != null)
|
||||||
|
{
|
||||||
|
moveCam += FarseerPhysics.ConvertUnits.ToDisplayUnits(closestSub.Velocity * deltaTime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,7 +315,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Freeze = true;
|
Freeze = true;
|
||||||
}
|
}
|
||||||
if (CharacterHealth.OpenHealthWindow != null || CrewManager.IsCommandInterfaceOpen)
|
if (CharacterHealth.OpenHealthWindow != null || CrewManager.IsCommandInterfaceOpen || ConversationAction.IsDialogOpen)
|
||||||
{
|
{
|
||||||
offset *= 0;
|
offset *= 0;
|
||||||
Freeze = false;
|
Freeze = false;
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
partial class HumanAIController : AIController
|
partial class HumanAIController : AIController
|
||||||
{
|
{
|
||||||
|
public static bool debugai;
|
||||||
|
|
||||||
partial void InitProjSpecific()
|
partial void InitProjSpecific()
|
||||||
{
|
{
|
||||||
/*if (GameMain.GameSession != null && GameMain.GameSession.CrewManager != null)
|
/*if (GameMain.GameSession != null && GameMain.GameSession.CrewManager != null)
|
||||||
@@ -18,6 +20,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public override void DebugDraw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch)
|
public override void DebugDraw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch)
|
||||||
{
|
{
|
||||||
|
if (Character == Character.Controlled) { return; }
|
||||||
|
if (!debugai) { return; }
|
||||||
Vector2 pos = Character.WorldPosition;
|
Vector2 pos = Character.WorldPosition;
|
||||||
pos.Y = -pos.Y;
|
pos.Y = -pos.Y;
|
||||||
Vector2 textOffset = new Vector2(-40, -160);
|
Vector2 textOffset = new Vector2(-40, -160);
|
||||||
|
|||||||
@@ -268,7 +268,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else if (body.UserData is Limb || body == Collider.FarseerBody)
|
else if (body.UserData is Limb || body == Collider.FarseerBody)
|
||||||
{
|
{
|
||||||
if (!character.IsRemotePlayer && impact > ImpactTolerance)
|
if (!character.IsRemotelyControlled && impact > ImpactTolerance)
|
||||||
{
|
{
|
||||||
SoundPlayer.PlayDamageSound("LimbBlunt", strongestImpact, Collider);
|
SoundPlayer.PlayDamageSound("LimbBlunt", strongestImpact, Collider);
|
||||||
}
|
}
|
||||||
@@ -460,21 +460,14 @@ namespace Barotrauma
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public float GetDepthOffset()
|
public float GetDepthOffset()
|
||||||
{
|
{
|
||||||
|
float maxDepth = 0.0f;
|
||||||
|
float minDepth = 1.0f;
|
||||||
float depthOffset = 0.0f;
|
float depthOffset = 0.0f;
|
||||||
var ladder = character.SelectedConstruction?.GetComponent<Ladder>();
|
var ladder = character.SelectedConstruction?.GetComponent<Ladder>();
|
||||||
|
|
||||||
if (ladder != null)
|
if (ladder != null)
|
||||||
{
|
{
|
||||||
float maxDepth = 0.0f;
|
CalculateLimbDepths();
|
||||||
float minDepth = 1.0f;
|
|
||||||
foreach (Limb limb in Limbs)
|
|
||||||
{
|
|
||||||
var activeSprite = limb.ActiveSprite;
|
|
||||||
if (activeSprite != null)
|
|
||||||
{
|
|
||||||
maxDepth = Math.Max(activeSprite.Depth, maxDepth);
|
|
||||||
minDepth = Math.Min(activeSprite.Depth, minDepth);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (character.WorldPosition.X < character.SelectedConstruction.WorldPosition.X)
|
if (character.WorldPosition.X < character.SelectedConstruction.WorldPosition.X)
|
||||||
{
|
{
|
||||||
//at the left side of the ladder, needs to be drawn in front of the rungs
|
//at the left side of the ladder, needs to be drawn in front of the rungs
|
||||||
@@ -486,6 +479,36 @@ namespace Barotrauma
|
|||||||
depthOffset = Math.Max(ladder.BackgroundSpriteDepth + 0.01f - minDepth, 0.0f);
|
depthOffset = Math.Max(ladder.BackgroundSpriteDepth + 0.01f - minDepth, 0.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CalculateLimbDepths();
|
||||||
|
var controller = character.SelectedConstruction?.GetComponent<Controller>();
|
||||||
|
if (controller != null && controller.ControlCharacterPose && controller.User == character)
|
||||||
|
{
|
||||||
|
if (controller.Item.SpriteDepth > maxDepth)
|
||||||
|
{
|
||||||
|
depthOffset = Math.Max(controller.Item.SpriteDepth - 0.0001f - maxDepth, 0.0f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
depthOffset = Math.Max(controller.Item.SpriteDepth + 0.0001f - minDepth, -minDepth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CalculateLimbDepths()
|
||||||
|
{
|
||||||
|
foreach (Limb limb in Limbs)
|
||||||
|
{
|
||||||
|
var activeSprite = limb.ActiveSprite;
|
||||||
|
if (activeSprite != null)
|
||||||
|
{
|
||||||
|
maxDepth = Math.Max(activeSprite.Depth, maxDepth);
|
||||||
|
minDepth = Math.Min(activeSprite.Depth, minDepth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return depthOffset;
|
return depthOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,10 +521,15 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (limb.PullJointEnabled)
|
if (limb.PullJointEnabled)
|
||||||
{
|
{
|
||||||
Vector2 pos = ConvertUnits.ToDisplayUnits(limb.PullJointWorldAnchorA);
|
Vector2 pos = ConvertUnits.ToDisplayUnits(limb.PullJointWorldAnchorB);
|
||||||
if (currentHull?.Submarine != null) pos += currentHull.Submarine.DrawPosition;
|
if (currentHull?.Submarine != null) pos += currentHull.Submarine.DrawPosition;
|
||||||
pos.Y = -pos.Y;
|
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), GUI.Style.Red, true, 0.01f);
|
||||||
|
|
||||||
|
pos = ConvertUnits.ToDisplayUnits(limb.PullJointWorldAnchorA);
|
||||||
|
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), Color.Cyan, true, 0.01f);
|
||||||
}
|
}
|
||||||
|
|
||||||
limb.body.DebugDraw(spriteBatch, inWater ? (currentHull == null ? Color.Blue : Color.Cyan) : Color.White);
|
limb.body.DebugDraw(spriteBatch, inWater ? (currentHull == null ? Color.Blue : Color.Cyan) : Color.White);
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
protected float soundTimer;
|
protected float soundTimer;
|
||||||
protected float soundInterval;
|
protected float soundInterval;
|
||||||
protected float hudInfoTimer;
|
protected float hudInfoTimer = 1.0f;
|
||||||
protected bool hudInfoVisible;
|
protected bool hudInfoVisible = false;
|
||||||
|
|
||||||
private float pressureParticleTimer;
|
private float pressureParticleTimer;
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
protected float lastRecvPositionUpdateTime;
|
protected float lastRecvPositionUpdateTime;
|
||||||
|
|
||||||
private float hudInfoHeight;
|
private float hudInfoHeight = 100.0f;
|
||||||
|
|
||||||
private List<CharacterSound> sounds;
|
private List<CharacterSound> sounds;
|
||||||
|
|
||||||
@@ -264,7 +264,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else if (Lights.LightManager.ViewTarget is Item item && item.Prefab.FocusOnSelected)
|
else if (Lights.LightManager.ViewTarget is Item item && item.Prefab.FocusOnSelected)
|
||||||
{
|
{
|
||||||
cam.OffsetAmount = targetOffsetAmount = item.Prefab.OffsetOnSelected;
|
cam.OffsetAmount = targetOffsetAmount = item.Prefab.OffsetOnSelected * item.OffsetOnSelectedMultiplier;
|
||||||
}
|
}
|
||||||
else if (SelectedConstruction != null && ViewTarget == null &&
|
else if (SelectedConstruction != null && ViewTarget == null &&
|
||||||
SelectedConstruction.Components.Any(ic => ic?.GuiFrame != null && ic.ShouldDrawHUD(this)))
|
SelectedConstruction.Components.Any(ic => ic?.GuiFrame != null && ic.ShouldDrawHUD(this)))
|
||||||
@@ -549,11 +549,12 @@ namespace Barotrauma
|
|||||||
public bool ShouldLockHud()
|
public bool ShouldLockHud()
|
||||||
{
|
{
|
||||||
if (this != controlled) { return false; }
|
if (this != controlled) { return false; }
|
||||||
|
if (GameMain.GameSession?.Campaign != null && GameMain.GameSession.Campaign.ShowCampaignUI) { return true; }
|
||||||
|
var controller = SelectedConstruction?.GetComponent<Controller>();
|
||||||
//lock if using a controller, except if we're also using a connection panel in the same item
|
//lock if using a controller, except if we're also using a connection panel in the same item
|
||||||
return
|
return
|
||||||
SelectedConstruction != null &&
|
SelectedConstruction != null &&
|
||||||
SelectedConstruction?.GetComponent<Controller>()?.User == this &&
|
controller?.User == this && controller.HideHUD &&
|
||||||
SelectedConstruction?.GetComponent<ConnectionPanel>()?.User != this;
|
SelectedConstruction?.GetComponent<ConnectionPanel>()?.User != this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -661,7 +662,7 @@ namespace Barotrauma
|
|||||||
public void DrawHUD(SpriteBatch spriteBatch, Camera cam, bool drawHealth = true)
|
public void DrawHUD(SpriteBatch spriteBatch, Camera cam, bool drawHealth = true)
|
||||||
{
|
{
|
||||||
CharacterHUD.Draw(spriteBatch, this, cam);
|
CharacterHUD.Draw(spriteBatch, this, cam);
|
||||||
if (drawHealth) CharacterHealth.DrawHUD(spriteBatch);
|
if (drawHealth && !CharacterHUD.IsCampaignInterfaceOpen) { CharacterHealth.DrawHUD(spriteBatch); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void DrawFront(SpriteBatch spriteBatch, Camera cam)
|
public virtual void DrawFront(SpriteBatch spriteBatch, Camera cam)
|
||||||
@@ -673,7 +674,7 @@ namespace Barotrauma
|
|||||||
AnimController.DebugDraw(spriteBatch);
|
AnimController.DebugDraw(spriteBatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GUI.DisableHUD) return;
|
if (GUI.DisableHUD) { return; }
|
||||||
|
|
||||||
if (Controlled != null &&
|
if (Controlled != null &&
|
||||||
Controlled != this &&
|
Controlled != this &&
|
||||||
@@ -756,19 +757,23 @@ namespace Barotrauma
|
|||||||
float hoverRange = 300.0f;
|
float hoverRange = 300.0f;
|
||||||
float fadeOutRange = 200.0f;
|
float fadeOutRange = 200.0f;
|
||||||
float cursorDist = Vector2.Distance(WorldPosition, cam.ScreenToWorld(PlayerInput.MousePosition));
|
float cursorDist = Vector2.Distance(WorldPosition, cam.ScreenToWorld(PlayerInput.MousePosition));
|
||||||
float hudInfoAlpha = MathHelper.Clamp(1.0f - (cursorDist - (hoverRange - fadeOutRange)) / fadeOutRange, 0.2f, 1.0f);
|
float hudInfoAlpha =
|
||||||
|
CampaignInteractionType == CampaignMode.InteractionType.None ?
|
||||||
|
MathHelper.Clamp(1.0f - (cursorDist - (hoverRange - fadeOutRange)) / fadeOutRange, 0.2f, 1.0f) :
|
||||||
|
1.0f;
|
||||||
|
|
||||||
if (!GUI.DisableCharacterNames && hudInfoVisible && info != null &&
|
if (!GUI.DisableCharacterNames && hudInfoVisible && info != null &&
|
||||||
(controlled == null || this != controlled.FocusedCharacter))
|
(controlled == null || this != controlled.FocusedCharacter) && cam.Zoom > 0.4f)
|
||||||
{
|
{
|
||||||
string name = Info.DisplayName;
|
string name = Info.DisplayName;
|
||||||
if (controlled == null && name != Info.Name) name += " " + TextManager.Get("Disguised");
|
if (controlled == null && name != Info.Name) { name += " " + TextManager.Get("Disguised"); }
|
||||||
|
|
||||||
Vector2 namePos = new Vector2(pos.X, pos.Y - 10.0f - (5.0f / cam.Zoom)) - GUI.Font.MeasureString(name) * 0.5f / cam.Zoom;
|
Vector2 nameSize = GUI.Font.MeasureString(name);
|
||||||
|
Vector2 namePos = new Vector2(pos.X, pos.Y - 10.0f - (5.0f / cam.Zoom)) - nameSize * 0.5f / cam.Zoom;
|
||||||
|
|
||||||
Vector2 screenSize = new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
Vector2 screenSize = new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||||
Vector2 viewportSize = new Vector2(cam.WorldView.Width, cam.WorldView.Height);
|
Vector2 viewportSize = new Vector2(cam.WorldView.Width, cam.WorldView.Height);
|
||||||
namePos.X -= cam.WorldView.X; namePos.Y += cam.WorldView.Y;
|
namePos.X -= cam.WorldView.X; namePos.Y += cam.WorldView.Y;
|
||||||
namePos *= screenSize / viewportSize;
|
namePos *= screenSize / viewportSize;
|
||||||
namePos.X = (float)Math.Floor(namePos.X); namePos.Y = (float)Math.Floor(namePos.Y);
|
namePos.X = (float)Math.Floor(namePos.X); namePos.Y = (float)Math.Floor(namePos.Y);
|
||||||
namePos *= viewportSize / screenSize;
|
namePos *= viewportSize / screenSize;
|
||||||
@@ -779,16 +784,30 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
nameColor = TeamID == TeamType.FriendlyNPC ? Color.SkyBlue : GUI.Style.Red;
|
nameColor = TeamID == TeamType.FriendlyNPC ? Color.SkyBlue : GUI.Style.Red;
|
||||||
}
|
}
|
||||||
|
if (CampaignInteractionType != CampaignMode.InteractionType.None && AllowCustomInteract)
|
||||||
|
{
|
||||||
|
var iconStyle = GUI.Style.GetComponentStyle("CampaignInteractionIcon." + CampaignInteractionType);
|
||||||
|
if (iconStyle != null)
|
||||||
|
{
|
||||||
|
Vector2 headPos = AnimController.GetLimb(LimbType.Head)?.WorldPosition ?? WorldPosition + Vector2.UnitY * 100.0f;
|
||||||
|
Vector2 iconPos = headPos;
|
||||||
|
iconPos.Y = -iconPos.Y;
|
||||||
|
nameColor = iconStyle.Color;
|
||||||
|
var icon = iconStyle.Sprites[GUIComponent.ComponentState.None].First();
|
||||||
|
float iconScale = 30.0f / icon.Sprite.size.X / cam.Zoom;
|
||||||
|
icon.Sprite.Draw(spriteBatch, iconPos + new Vector2(-35.0f, -25.0f), iconStyle.Color * hudInfoAlpha, scale: iconScale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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 + 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);
|
GUI.Font.DrawString(spriteBatch, name, namePos, nameColor * hudInfoAlpha, 0.0f, Vector2.Zero, 1.0f / cam.Zoom, SpriteEffects.None, 0.0f);
|
||||||
|
|
||||||
if (GameMain.DebugDraw)
|
if (GameMain.DebugDraw)
|
||||||
{
|
{
|
||||||
GUI.Font.DrawString(spriteBatch, ID.ToString(), namePos - new Vector2(0.0f, 20.0f), Color.White);
|
GUI.Font.DrawString(spriteBatch, ID.ToString(), namePos - new Vector2(0.0f, 20.0f), Color.White);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsDead) return;
|
if (IsDead) { return; }
|
||||||
|
|
||||||
if (CharacterHealth.DisplayedVitality < MaxVitality * 0.98f && hudInfoVisible)
|
if (CharacterHealth.DisplayedVitality < MaxVitality * 0.98f && hudInfoVisible)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -41,13 +41,21 @@ namespace Barotrauma
|
|||||||
private static bool shouldRecreateHudTexts = true;
|
private static bool shouldRecreateHudTexts = true;
|
||||||
private static bool heldDownShiftWhenGotHudTexts;
|
private static bool heldDownShiftWhenGotHudTexts;
|
||||||
|
|
||||||
|
public static bool IsCampaignInterfaceOpen =>
|
||||||
|
GameMain.GameSession?.Campaign != null &&
|
||||||
|
(GameMain.GameSession.Campaign.ShowCampaignUI || GameMain.GameSession.Campaign.ForceMapUI);
|
||||||
|
|
||||||
private static bool ShouldDrawInventory(Character character)
|
private static bool ShouldDrawInventory(Character character)
|
||||||
{
|
{
|
||||||
|
var controller = character.SelectedConstruction?.GetComponent<Controller>();
|
||||||
|
|
||||||
return
|
return
|
||||||
character?.Inventory != null &&
|
character?.Inventory != null &&
|
||||||
character.AllowInput &&
|
character.AllowInput &&
|
||||||
!character.LockHands &&
|
!character.LockHands &&
|
||||||
character.SelectedConstruction?.GetComponent<Controller>()?.User != character;
|
(controller?.User != character || !controller.HideHUD) &&
|
||||||
|
!IsCampaignInterfaceOpen &&
|
||||||
|
!ConversationAction.FadeScreenToBlack;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetCachedHudText(string textTag, string keyBind)
|
private static string GetCachedHudText(string textTag, string keyBind)
|
||||||
@@ -65,7 +73,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (GUI.DisableHUD) return;
|
if (GUI.DisableHUD) return;
|
||||||
|
|
||||||
if (!character.IsIncapacitated && character.Stun <= 0.0f)
|
if (!character.IsIncapacitated && character.Stun <= 0.0f && !IsCampaignInterfaceOpen)
|
||||||
{
|
{
|
||||||
if (character.Inventory != null)
|
if (character.Inventory != null)
|
||||||
{
|
{
|
||||||
@@ -92,9 +100,17 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public static void Update(float deltaTime, Character character, Camera cam)
|
public static void Update(float deltaTime, Character character, Camera cam)
|
||||||
{
|
{
|
||||||
if (GUI.DisableHUD) { return; }
|
if (GUI.DisableHUD)
|
||||||
|
{
|
||||||
|
if (character.Inventory != null && !LockInventory(character))
|
||||||
|
{
|
||||||
|
character.Inventory.UpdateSlotInput();
|
||||||
|
}
|
||||||
|
|
||||||
if (!character.IsIncapacitated && character.Stun <= 0.0f)
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!character.IsIncapacitated && character.Stun <= 0.0f && !IsCampaignInterfaceOpen)
|
||||||
{
|
{
|
||||||
if (character.Info != null && !character.ShouldLockHud() && character.SelectedCharacter == null)
|
if (character.Info != null && !character.ShouldLockHud() && character.SelectedCharacter == null)
|
||||||
{
|
{
|
||||||
@@ -163,7 +179,7 @@ namespace Barotrauma
|
|||||||
foreach (Item item in Item.ItemList)
|
foreach (Item item in Item.ItemList)
|
||||||
{
|
{
|
||||||
if (item.Submarine == null || item.Submarine.TeamID != character.TeamID || item.Submarine.Info.IsWreck) { continue; }
|
if (item.Submarine == null || item.Submarine.TeamID != character.TeamID || item.Submarine.Info.IsWreck) { continue; }
|
||||||
if (!item.Repairables.Any(r => item.ConditionPercentage <= r.RepairThreshold)) { continue; }
|
if (!item.Repairables.Any(r => item.ConditionPercentage <= r.RepairIconThreshold)) { continue; }
|
||||||
if (Submarine.VisibleEntities != null && !Submarine.VisibleEntities.Contains(item)) { continue; }
|
if (Submarine.VisibleEntities != null && !Submarine.VisibleEntities.Contains(item)) { continue; }
|
||||||
|
|
||||||
Vector2 diff = item.WorldPosition - character.WorldPosition;
|
Vector2 diff = item.WorldPosition - character.WorldPosition;
|
||||||
@@ -211,7 +227,7 @@ namespace Barotrauma
|
|||||||
Color.Lerp(GUI.Style.Red, GUI.Style.Orange * 0.5f, brokenItem.Condition / brokenItem.MaxCondition) * alpha);
|
Color.Lerp(GUI.Style.Red, GUI.Style.Orange * 0.5f, brokenItem.Condition / brokenItem.MaxCondition) * alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!character.IsIncapacitated && character.Stun <= 0.0f)
|
if (!character.IsIncapacitated && character.Stun <= 0.0f && !IsCampaignInterfaceOpen)
|
||||||
{
|
{
|
||||||
if (character.FocusedCharacter != null && character.FocusedCharacter.CanBeSelected)
|
if (character.FocusedCharacter != null && character.FocusedCharacter.CanBeSelected)
|
||||||
{
|
{
|
||||||
@@ -299,6 +315,8 @@ namespace Barotrauma
|
|||||||
character.SelectedConstruction.DrawHUD(spriteBatch, cam, Character.Controlled);
|
character.SelectedConstruction.DrawHUD(spriteBatch, cam, Character.Controlled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsCampaignInterfaceOpen) { return; }
|
||||||
|
|
||||||
if (character.Inventory != null)
|
if (character.Inventory != null)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < character.Inventory.Items.Length - 1; i++)
|
for (int i = 0; i < character.Inventory.Items.Length - 1; i++)
|
||||||
@@ -308,10 +326,11 @@ namespace Barotrauma
|
|||||||
|
|
||||||
foreach (ItemComponent ic in item.Components)
|
foreach (ItemComponent ic in item.Components)
|
||||||
{
|
{
|
||||||
if (ic.DrawHudWhenEquipped) ic.DrawHUD(spriteBatch, character);
|
if (ic.DrawHudWhenEquipped) { ic.DrawHUD(spriteBatch, character); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mouseOnPortrait = false;
|
bool mouseOnPortrait = false;
|
||||||
if (character.Stun <= 0.1f && !character.IsDead)
|
if (character.Stun <= 0.1f && !character.IsDead)
|
||||||
{
|
{
|
||||||
@@ -421,7 +440,7 @@ namespace Barotrauma
|
|||||||
GUI.Style.Green, Color.Black, 2, GUI.SmallFont);
|
GUI.Style.Green, Color.Black, 2, GUI.SmallFont);
|
||||||
textPos.Y += textSize.Y;
|
textPos.Y += textSize.Y;
|
||||||
}
|
}
|
||||||
if (!string.IsNullOrEmpty(character.FocusedCharacter.customInteractHUDText))
|
if (!string.IsNullOrEmpty(character.FocusedCharacter.customInteractHUDText) && 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, GUI.Style.Green, Color.Black, 2, GUI.SmallFont);
|
||||||
textPos.Y += textSize.Y;
|
textPos.Y += textSize.Y;
|
||||||
@@ -430,7 +449,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private static bool LockInventory(Character character)
|
private static bool LockInventory(Character character)
|
||||||
{
|
{
|
||||||
if (character?.Inventory == null || !character.AllowInput || character.LockHands) { return true; }
|
if (character?.Inventory == null || !character.AllowInput || character.LockHands || IsCampaignInterfaceOpen) { return true; }
|
||||||
|
|
||||||
return character.ShouldLockHud();
|
return character.ShouldLockHud();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using System.Linq;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -12,9 +13,11 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
private static Sprite infoAreaPortraitBG;
|
private static Sprite infoAreaPortraitBG;
|
||||||
|
|
||||||
|
public bool LastControlled;
|
||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
{
|
||||||
infoAreaPortraitBG = GUI.Style.GetComponentStyle("InfoAreaPortraitBG")?.Sprites[GUIComponent.ComponentState.None][0].Sprite;
|
infoAreaPortraitBG = GUI.Style.GetComponentStyle("InfoAreaPortraitBG")?.GetDefaultSprite();
|
||||||
new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(833, 298, 142, 98), null, 0);
|
new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(833, 298, 142, 98), null, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,6 +120,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private void DrawInfoFrameCharacterIcon(SpriteBatch sb, Rectangle componentRect)
|
private void DrawInfoFrameCharacterIcon(SpriteBatch sb, Rectangle componentRect)
|
||||||
{
|
{
|
||||||
|
if (headSprite == null) { return; }
|
||||||
Vector2 targetAreaSize = componentRect.Size.ToVector2();
|
Vector2 targetAreaSize = componentRect.Size.ToVector2();
|
||||||
float scale = Math.Min(targetAreaSize.X / headSprite.size.X, targetAreaSize.Y / headSprite.size.Y);
|
float scale = Math.Min(targetAreaSize.X / headSprite.size.X, targetAreaSize.Y / headSprite.size.Y);
|
||||||
DrawIcon(sb, componentRect.Location.ToVector2() + headSprite.size / 2 * scale, targetAreaSize);
|
DrawIcon(sb, componentRect.Location.ToVector2() + headSprite.size / 2 * scale, targetAreaSize);
|
||||||
@@ -140,6 +144,9 @@ namespace Barotrauma
|
|||||||
|
|
||||||
partial void OnSkillChanged(string skillIdentifier, float prevLevel, float newLevel, Vector2 textPopupPos)
|
partial void OnSkillChanged(string skillIdentifier, float prevLevel, float newLevel, Vector2 textPopupPos)
|
||||||
{
|
{
|
||||||
|
if (TeamID == Character.TeamType.FriendlyNPC) { return; }
|
||||||
|
if (Character.Controlled != null && Character.Controlled.TeamID != TeamID) { return; }
|
||||||
|
|
||||||
if (newLevel - prevLevel > 0.1f)
|
if (newLevel - prevLevel > 0.1f)
|
||||||
{
|
{
|
||||||
GUI.AddMessage(
|
GUI.AddMessage(
|
||||||
|
|||||||
@@ -75,8 +75,15 @@ namespace Barotrauma
|
|||||||
states = newInput,
|
states = newInput,
|
||||||
intAim = intAngle
|
intAim = intAngle
|
||||||
};
|
};
|
||||||
if (focusedItem != null && !CharacterInventory.DraggingItemToWorld &&
|
|
||||||
(!newMem.states.HasFlag(InputNetFlags.Grab) && !newMem.states.HasFlag(InputNetFlags.Health)))
|
if (FocusedCharacter != null &&
|
||||||
|
FocusedCharacter.CampaignInteractionType != CampaignMode.InteractionType.None &&
|
||||||
|
newMem.states.HasFlag(InputNetFlags.Use))
|
||||||
|
{
|
||||||
|
newMem.interact = FocusedCharacter.ID;
|
||||||
|
}
|
||||||
|
else if (focusedItem != null && !CharacterInventory.DraggingItemToWorld &&
|
||||||
|
!newMem.states.HasFlag(InputNetFlags.Grab) && !newMem.states.HasFlag(InputNetFlags.Health))
|
||||||
{
|
{
|
||||||
newMem.interact = focusedItem.ID;
|
newMem.interact = focusedItem.ID;
|
||||||
}
|
}
|
||||||
@@ -278,10 +285,10 @@ namespace Barotrauma
|
|||||||
break;
|
break;
|
||||||
case ServerNetObject.ENTITY_EVENT:
|
case ServerNetObject.ENTITY_EVENT:
|
||||||
|
|
||||||
int eventType = msg.ReadRangedInteger(0, 4);
|
int eventType = msg.ReadRangedInteger(0, 5);
|
||||||
switch (eventType)
|
switch (eventType)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0: //NetEntityEvent.Type.InventoryState
|
||||||
if (Inventory == null)
|
if (Inventory == null)
|
||||||
{
|
{
|
||||||
string errorMsg = "Received an inventory update message for an entity with no inventory (" + Name + ", removed: " + Removed + ")";
|
string errorMsg = "Received an inventory update message for an entity with no inventory (" + Name + ", removed: " + Removed + ")";
|
||||||
@@ -301,7 +308,7 @@ namespace Barotrauma
|
|||||||
Inventory.ClientRead(type, msg, sendingTime);
|
Inventory.ClientRead(type, msg, sendingTime);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1: //NetEntityEvent.Type.Control
|
||||||
byte ownerID = msg.ReadByte();
|
byte ownerID = msg.ReadByte();
|
||||||
ResetNetState();
|
ResetNetState();
|
||||||
if (ownerID == GameMain.Client.ID)
|
if (ownerID == GameMain.Client.ID)
|
||||||
@@ -326,10 +333,10 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2: //NetEntityEvent.Type.Status
|
||||||
ReadStatus(msg);
|
ReadStatus(msg);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3: //NetEntityEvent.Type.UpdateSkills
|
||||||
int skillCount = msg.ReadByte();
|
int skillCount = msg.ReadByte();
|
||||||
for (int i = 0; i < skillCount; i++)
|
for (int i = 0; i < skillCount; i++)
|
||||||
{
|
{
|
||||||
@@ -338,17 +345,17 @@ namespace Barotrauma
|
|||||||
info?.SetSkillLevel(skillIdentifier, skillLevel, WorldPosition + Vector2.UnitY * 150.0f);
|
info?.SetSkillLevel(skillIdentifier, skillLevel, WorldPosition + Vector2.UnitY * 150.0f);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4: //NetEntityEvent.Type.ExecuteAttack
|
||||||
int attackLimbIndex = msg.ReadByte();
|
int attackLimbIndex = msg.ReadByte();
|
||||||
UInt16 targetEntityID = msg.ReadUInt16();
|
UInt16 targetEntityID = msg.ReadUInt16();
|
||||||
int targetLimbIndex = msg.ReadByte();
|
int targetLimbIndex = msg.ReadByte();
|
||||||
|
|
||||||
//255 = entity already removed, no need to do anything
|
//255 = entity already removed, no need to do anything
|
||||||
if (attackLimbIndex == 255) { break; }
|
if (attackLimbIndex == 255 || Removed) { break; }
|
||||||
|
|
||||||
if (attackLimbIndex >= AnimController.Limbs.Length)
|
if (attackLimbIndex >= AnimController.Limbs.Length)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError($"Received invalid ExecuteAttack message. Limb index out of bounds ({attackLimbIndex})");
|
DebugConsole.ThrowError($"Received invalid ExecuteAttack message. Limb index out of bounds (character: {Name}, limb index: {attackLimbIndex}, limb count: {AnimController.Limbs.Length})");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Limb attackLimb = AnimController.Limbs[attackLimbIndex];
|
Limb attackLimb = AnimController.Limbs[attackLimbIndex];
|
||||||
@@ -362,7 +369,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (targetLimbIndex >= targetCharacter.AnimController.Limbs.Length)
|
if (targetLimbIndex >= targetCharacter.AnimController.Limbs.Length)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError($"Received invalid ExecuteAttack message. Target limb index out of bounds ({targetLimbIndex})");
|
DebugConsole.ThrowError($"Received invalid ExecuteAttack message. Target limb index out of bounds (target character: {targetCharacter.Name}, limb index: {targetLimbIndex}, limb count: {targetCharacter.AnimController.Limbs.Length})");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
targetLimb = targetCharacter.AnimController.Limbs[targetLimbIndex];
|
targetLimb = targetCharacter.AnimController.Limbs[targetLimbIndex];
|
||||||
@@ -372,6 +379,10 @@ namespace Barotrauma
|
|||||||
attackLimb.ExecuteAttack(targetEntity, targetLimb, out _);
|
attackLimb.ExecuteAttack(targetEntity, targetLimb, out _);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 5: //NetEntityEvent.Type.AssignCampaignInteraction
|
||||||
|
byte campaignInteractionType = msg.ReadByte();
|
||||||
|
(GameMain.GameSession?.GameMode as CampaignMode)?.AssignNPCMenuInteraction(this, (CampaignMode.InteractionType)campaignInteractionType);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
msg.ReadPadBits();
|
msg.ReadPadBits();
|
||||||
break;
|
break;
|
||||||
@@ -398,7 +409,7 @@ namespace Barotrauma
|
|||||||
Character character = null;
|
Character character = null;
|
||||||
if (noInfo)
|
if (noInfo)
|
||||||
{
|
{
|
||||||
character = Create(speciesName, position, seed, null, true);
|
character = Create(speciesName, position, seed, null, false);
|
||||||
character.ID = id;
|
character.ID = id;
|
||||||
bool containsStatusData = inc.ReadBoolean();
|
bool containsStatusData = inc.ReadBoolean();
|
||||||
if (containsStatusData)
|
if (containsStatusData)
|
||||||
@@ -416,9 +427,14 @@ namespace Barotrauma
|
|||||||
|
|
||||||
CharacterInfo info = CharacterInfo.ClientRead(infoSpeciesName, inc);
|
CharacterInfo info = CharacterInfo.ClientRead(infoSpeciesName, inc);
|
||||||
|
|
||||||
character = Create(speciesName, position, seed, info, GameMain.Client.ID != ownerId, hasAi);
|
character = Create(speciesName, position, seed, info, ownerId > 0 && GameMain.Client.ID != ownerId, hasAi);
|
||||||
character.ID = id;
|
character.ID = id;
|
||||||
character.TeamID = (TeamType)teamID;
|
character.TeamID = (TeamType)teamID;
|
||||||
|
character.CampaignInteractionType = (CampaignMode.InteractionType)inc.ReadByte();
|
||||||
|
if (character.CampaignInteractionType != CampaignMode.InteractionType.None)
|
||||||
|
{
|
||||||
|
(GameMain.GameSession.GameMode as CampaignMode)?.AssignNPCMenuInteraction(character, character.CampaignInteractionType);
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the character has a current order
|
// Check if the character has a current order
|
||||||
if (inc.ReadBoolean())
|
if (inc.ReadBoolean())
|
||||||
|
|||||||
@@ -525,6 +525,7 @@ namespace Barotrauma
|
|||||||
},
|
},
|
||||||
TextManager.Get("GiveInButton"), style: "GUIButtonLarge")
|
TextManager.Get("GiveInButton"), style: "GUIButtonLarge")
|
||||||
{
|
{
|
||||||
|
Visible = false,
|
||||||
ToolTip = TextManager.Get(GameMain.NetworkMember == null ? "GiveInHelpSingleplayer" : "GiveInHelpMultiplayer"),
|
ToolTip = TextManager.Get(GameMain.NetworkMember == null ? "GiveInHelpSingleplayer" : "GiveInHelpMultiplayer"),
|
||||||
OnClicked = (button, userData) =>
|
OnClicked = (button, userData) =>
|
||||||
{
|
{
|
||||||
@@ -944,6 +945,22 @@ namespace Barotrauma
|
|||||||
|
|
||||||
suicideButton.Visible = Character == Character.Controlled && !Character.IsDead && Character.IsIncapacitated;
|
suicideButton.Visible = Character == Character.Controlled && !Character.IsDead && Character.IsIncapacitated;
|
||||||
|
|
||||||
|
if (GameMain.GameSession?.Campaign is { } campaign)
|
||||||
|
{
|
||||||
|
RectTransform endRoundButton = campaign?.EndRoundButton.RectTransform;
|
||||||
|
if (endRoundButton != null)
|
||||||
|
{
|
||||||
|
if (suicideButton.Visible)
|
||||||
|
{
|
||||||
|
endRoundButton.ScreenSpaceOffset = new Point(0, suicideButton.Rect.Height);
|
||||||
|
}
|
||||||
|
else if (endRoundButton.ScreenSpaceOffset != Point.Zero)
|
||||||
|
{
|
||||||
|
endRoundButton.ScreenSpaceOffset = Point.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cprButton.Visible =
|
cprButton.Visible =
|
||||||
Character == Character.Controlled?.SelectedCharacter
|
Character == Character.Controlled?.SelectedCharacter
|
||||||
&& (Character.IsUnconscious || Character.Stun > 0.0f)
|
&& (Character.IsUnconscious || Character.Stun > 0.0f)
|
||||||
@@ -965,23 +982,29 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void AddToGUIUpdateList()
|
public void AddToGUIUpdateList()
|
||||||
{
|
{
|
||||||
if (GUI.DisableHUD) return;
|
if (GUI.DisableHUD) { return; }
|
||||||
if (OpenHealthWindow == this)
|
if (OpenHealthWindow == this)
|
||||||
{
|
{
|
||||||
healthInterfaceFrame.AddToGUIUpdateList();
|
healthInterfaceFrame.AddToGUIUpdateList();
|
||||||
afflictionTooltip?.AddToGUIUpdateList();
|
afflictionTooltip?.AddToGUIUpdateList();
|
||||||
}
|
}
|
||||||
else if (Character.Controlled == Character)
|
else if (Character.Controlled == Character && !CharacterHUD.IsCampaignInterfaceOpen)
|
||||||
{
|
{
|
||||||
healthBarHolder.AddToGUIUpdateList();
|
healthBarHolder.AddToGUIUpdateList();
|
||||||
}
|
}
|
||||||
if (suicideButton.Visible && Character == Character.Controlled) suicideButton.AddToGUIUpdateList();
|
if (suicideButton.Visible && Character == Character.Controlled)
|
||||||
if (cprButton != null && cprButton.Visible) cprButton.AddToGUIUpdateList();
|
{
|
||||||
|
suicideButton.AddToGUIUpdateList();
|
||||||
|
}
|
||||||
|
if (cprButton != null && cprButton.Visible)
|
||||||
|
{
|
||||||
|
cprButton.AddToGUIUpdateList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DrawHUD(SpriteBatch spriteBatch)
|
public void DrawHUD(SpriteBatch spriteBatch)
|
||||||
{
|
{
|
||||||
if (GUI.DisableHUD) return;
|
if (GUI.DisableHUD) { return; }
|
||||||
if (GameMain.GraphicsWidth != screenResolution.X ||
|
if (GameMain.GraphicsWidth != screenResolution.X ||
|
||||||
GameMain.GraphicsHeight != screenResolution.Y ||
|
GameMain.GraphicsHeight != screenResolution.Y ||
|
||||||
Math.Abs(inventoryScale - Inventory.UIScale) > 0.01f ||
|
Math.Abs(inventoryScale - Inventory.UIScale) > 0.01f ||
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
partial class JobPrefab : IPrefab, IDisposable
|
partial class JobPrefab : IPrefab, IDisposable
|
||||||
{
|
{
|
||||||
public GUIButton CreateInfoFrame(int variant)
|
public GUIButton CreateInfoFrame(out GUIComponent buttonContainer)
|
||||||
{
|
{
|
||||||
int width = 500, height = 400;
|
int width = 500, height = 400;
|
||||||
|
|
||||||
@@ -34,6 +34,8 @@ namespace Barotrauma
|
|||||||
font: GUI.SmallFont);
|
font: GUI.SmallFont);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buttonContainer = paddedFrame;
|
||||||
|
|
||||||
/*if (!ItemIdentifiers.TryGetValue(variant, out var itemIdentifiers)) { return backFrame; }
|
/*if (!ItemIdentifiers.TryGetValue(variant, out var itemIdentifiers)) { return backFrame; }
|
||||||
var itemContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.45f, 0.5f), paddedFrame.RectTransform, Anchor.TopRight)
|
var itemContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.45f, 0.5f), paddedFrame.RectTransform, Anchor.TopRight)
|
||||||
{ RelativeOffset = new Vector2(0.0f, 0.2f + descriptionBlock.RectTransform.RelativeSize.Y) })
|
{ RelativeOffset = new Vector2(0.0f, 0.2f + descriptionBlock.RectTransform.RelativeSize.Y) })
|
||||||
@@ -54,7 +56,6 @@ namespace Barotrauma
|
|||||||
return frameHolder;
|
return frameHolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public class OutfitPreview
|
public class OutfitPreview
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -50,7 +50,12 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static bool isOpen;
|
private static bool isOpen;
|
||||||
public static bool IsOpen => isOpen;
|
public static bool IsOpen
|
||||||
|
{
|
||||||
|
get => isOpen;
|
||||||
|
set => isOpen = value;
|
||||||
|
}
|
||||||
|
|
||||||
public static bool Paused = false;
|
public static bool Paused = false;
|
||||||
|
|
||||||
private static GUITextBlock activeQuestionText;
|
private static GUITextBlock activeQuestionText;
|
||||||
@@ -66,6 +71,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
{
|
||||||
|
OpenAL.Alc.SetErrorReasonCallback((string msg) => NewMessage(msg, Color.Orange));
|
||||||
|
|
||||||
frame = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.45f), GUI.Canvas) { MinSize = new Point(400, 300), AbsoluteOffset = new Point(10, 10) },
|
frame = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.45f), GUI.Canvas) { MinSize = new Point(400, 300), AbsoluteOffset = new Point(10, 10) },
|
||||||
color: new Color(0.4f, 0.4f, 0.4f, 0.8f));
|
color: new Color(0.4f, 0.4f, 0.4f, 0.8f));
|
||||||
|
|
||||||
@@ -263,12 +270,31 @@ namespace Barotrauma
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), listBox.Content.RectTransform),
|
if (msg.IsError)
|
||||||
msg.Text, font: GUI.SmallFont, wrap: true)
|
|
||||||
{
|
{
|
||||||
CanBeFocused = false,
|
var textContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.0f), listBox.Content.RectTransform), style: "InnerFrame", color: Color.White)
|
||||||
TextColor = msg.Color
|
{
|
||||||
};
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
var textBlock = new GUITextBlock(new RectTransform(new Point(listBox.Content.Rect.Width - 5, 0), textContainer.RectTransform, Anchor.TopLeft) { AbsoluteOffset = new Point(2, 2) },
|
||||||
|
msg.Text, textAlignment: Alignment.TopLeft, font: GUI.SmallFont, wrap: true)
|
||||||
|
{
|
||||||
|
CanBeFocused = false,
|
||||||
|
TextColor = msg.Color
|
||||||
|
};
|
||||||
|
textContainer.RectTransform.NonScaledSize = new Point(textContainer.RectTransform.NonScaledSize.X, textBlock.RectTransform.NonScaledSize.Y + 5);
|
||||||
|
textBlock.SetTextPos();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), listBox.Content.RectTransform),
|
||||||
|
msg.Text, font: GUI.SmallFont, wrap: true)
|
||||||
|
{
|
||||||
|
CanBeFocused = false,
|
||||||
|
TextColor = msg.Color
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
listBox.UpdateScrollBarSize();
|
listBox.UpdateScrollBarSize();
|
||||||
listBox.BarScroll = 1.0f;
|
listBox.BarScroll = 1.0f;
|
||||||
}
|
}
|
||||||
@@ -447,6 +473,11 @@ namespace Barotrauma
|
|||||||
GameMain.SpriteEditorScreen.Select();
|
GameMain.SpriteEditorScreen.Select();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
commands.Add(new Command("editevents|eventeditor", "editevents/eventeditor: Switch to the Event Editor to edit scripted events.", (string[] args) =>
|
||||||
|
{
|
||||||
|
GameMain.EventEditorScreen.Select();
|
||||||
|
}));
|
||||||
|
|
||||||
commands.Add(new Command("editcharacters|charactereditor", "editcharacters/charactereditor: Switch to the Character Editor to edit/create the ragdolls and animations of characters.", (string[] args) =>
|
commands.Add(new Command("editcharacters|charactereditor", "editcharacters/charactereditor: Switch to the Character Editor to edit/create the ragdolls and animations of characters.", (string[] args) =>
|
||||||
{
|
{
|
||||||
if (Screen.Selected == GameMain.GameScreen)
|
if (Screen.Selected == GameMain.GameScreen)
|
||||||
@@ -456,9 +487,11 @@ namespace Barotrauma
|
|||||||
GameMain.CharacterEditorScreen.Select();
|
GameMain.CharacterEditorScreen.Select();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
commands.Add(new Command("steamnetdebug", "steamnetdebug: Toggles Steamworks debug logging.", (string[] args) =>
|
commands.Add(new Command("steamnetdebug", "steamnetdebug: Toggles Steamworks networking debug logging.", (string[] args) =>
|
||||||
{
|
{
|
||||||
SteamManager.NetworkingDebugLog = !SteamManager.NetworkingDebugLog;
|
SteamManager.NetworkingDebugLog = !SteamManager.NetworkingDebugLog;
|
||||||
|
SteamManager.SetSteamworksNetworkingDebugLog(SteamManager.NetworkingDebugLog);
|
||||||
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
AssignRelayToServer("kick", false);
|
AssignRelayToServer("kick", false);
|
||||||
@@ -493,6 +526,7 @@ namespace Barotrauma
|
|||||||
commands.Add(new Command("traitorlist", "", (string[] args) => { }));
|
commands.Add(new Command("traitorlist", "", (string[] args) => { }));
|
||||||
AssignRelayToServer("traitorlist", true);
|
AssignRelayToServer("traitorlist", true);
|
||||||
AssignRelayToServer("money", true);
|
AssignRelayToServer("money", true);
|
||||||
|
AssignRelayToServer("setskill", true);
|
||||||
|
|
||||||
AssignOnExecute("control", (string[] args) =>
|
AssignOnExecute("control", (string[] args) =>
|
||||||
{
|
{
|
||||||
@@ -568,16 +602,46 @@ namespace Barotrauma
|
|||||||
|
|
||||||
AssignOnExecute("ambientlight", (string[] args) =>
|
AssignOnExecute("ambientlight", (string[] args) =>
|
||||||
{
|
{
|
||||||
Color color = XMLExtensions.ParseColor(string.Join(",", args));
|
bool add = string.Equals(args.LastOrDefault(), "add");
|
||||||
|
string colorString = string.Join(",", add ? args.SkipLast(1) : args);
|
||||||
|
if (colorString.Equals("restore", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
foreach (Hull hull in Hull.hullList)
|
||||||
|
{
|
||||||
|
if (hull.OriginalAmbientLight != null)
|
||||||
|
{
|
||||||
|
hull.AmbientLight = hull.OriginalAmbientLight.Value;
|
||||||
|
hull.OriginalAmbientLight = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NewMessage("Restored all hull ambient lights", Color.White);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color color = XMLExtensions.ParseColor(colorString);
|
||||||
if (Level.Loaded != null)
|
if (Level.Loaded != null)
|
||||||
{
|
{
|
||||||
Level.Loaded.GenerationParams.AmbientLightColor = color;
|
Level.Loaded.GenerationParams.AmbientLightColor = color;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GameMain.LightManager.AmbientLight = color;
|
GameMain.LightManager.AmbientLight = add ? GameMain.LightManager.AmbientLight.Add(color) : color;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Hull hull in Hull.hullList)
|
||||||
|
{
|
||||||
|
hull.OriginalAmbientLight ??= hull.AmbientLight;
|
||||||
|
hull.AmbientLight = add ? hull.AmbientLight.Add(color) : color;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (add)
|
||||||
|
{
|
||||||
|
NewMessage($"Set ambient light color to {color}.", Color.White);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NewMessage($"Increased ambient light by {color}.", Color.White);
|
||||||
}
|
}
|
||||||
NewMessage("Set ambient light color to " + color + ".", Color.White);
|
|
||||||
});
|
});
|
||||||
AssignRelayToServer("ambientlight", false);
|
AssignRelayToServer("ambientlight", false);
|
||||||
|
|
||||||
@@ -849,17 +913,6 @@ namespace Barotrauma
|
|||||||
TutorialMode.StartTutorial(Tutorials.Tutorial.Tutorials[0]);
|
TutorialMode.StartTutorial(Tutorials.Tutorial.Tutorials[0]);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
commands.Add(new Command("lobby|lobbyscreen", "", (string[] args) =>
|
|
||||||
{
|
|
||||||
if (GameMain.Client != null)
|
|
||||||
{
|
|
||||||
ThrowError("This command cannot be used in multiplayer.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GameMain.LobbyScreen.Select();
|
|
||||||
}));
|
|
||||||
|
|
||||||
commands.Add(new Command("save|savesub", "save [submarine name]: Save the currently loaded submarine using the specified name.", (string[] args) =>
|
commands.Add(new Command("save|savesub", "save [submarine name]: Save the currently loaded submarine using the specified name.", (string[] args) =>
|
||||||
{
|
{
|
||||||
if (args.Length < 1) { return; }
|
if (args.Length < 1) { return; }
|
||||||
@@ -1011,9 +1064,39 @@ namespace Barotrauma
|
|||||||
});
|
});
|
||||||
AssignRelayToServer("toggleaitargets|aitargets", false);
|
AssignRelayToServer("toggleaitargets|aitargets", false);
|
||||||
|
|
||||||
|
AssignOnExecute("debugai", (string[] args) =>
|
||||||
|
{
|
||||||
|
HumanAIController.debugai = !HumanAIController.debugai;
|
||||||
|
if (HumanAIController.debugai)
|
||||||
|
{
|
||||||
|
GameMain.DebugDraw = true;
|
||||||
|
GameMain.LightManager.LightingEnabled = false;
|
||||||
|
GameMain.LightManager.LosEnabled = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GameMain.DebugDraw = false;
|
||||||
|
GameMain.LightManager.LightingEnabled = true;
|
||||||
|
GameMain.LightManager.LosEnabled = true;
|
||||||
|
}
|
||||||
|
NewMessage(HumanAIController.debugai ? "AI debug info visible" : "AI debug info hidden", Color.White);
|
||||||
|
});
|
||||||
|
AssignRelayToServer("debugai", false);
|
||||||
|
|
||||||
AssignRelayToServer("water|editwater", false);
|
AssignRelayToServer("water|editwater", false);
|
||||||
AssignRelayToServer("fire|editfire", false);
|
AssignRelayToServer("fire|editfire", false);
|
||||||
|
|
||||||
|
commands.Add(new Command("togglecampaignteleport", "togglecampaignteleport: Toggle on/off teleportation between campaign locations by double clicking on the campaign map.", (string[] args) =>
|
||||||
|
{
|
||||||
|
if (GameMain.GameSession?.Campaign == null)
|
||||||
|
{
|
||||||
|
ThrowError("No campaign active.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GameMain.GameSession.Map.AllowDebugTeleport = !GameMain.GameSession.Map.AllowDebugTeleport;
|
||||||
|
NewMessage((GameMain.GameSession.Map.AllowDebugTeleport ? "Enabled" : "Disabled") + " teleportation on the campaign map.", Color.White);
|
||||||
|
}, isCheat: true));
|
||||||
|
|
||||||
commands.Add(new Command("mute", "mute [name]: Prevent the client from speaking to anyone through the voice chat. Using this command requires a permission from the server host.",
|
commands.Add(new Command("mute", "mute [name]: Prevent the client from speaking to anyone through the voice chat. Using this command requires a permission from the server host.",
|
||||||
null,
|
null,
|
||||||
() =>
|
() =>
|
||||||
@@ -1044,7 +1127,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
foreach (ItemPrefab itemPrefab in ItemPrefab.Prefabs)
|
foreach (ItemPrefab itemPrefab in ItemPrefab.Prefabs)
|
||||||
{
|
{
|
||||||
int? minCost = itemPrefab.GetPrices()?.Min(p => p.BuyPrice);
|
int? minCost = itemPrefab.GetMinPrice();
|
||||||
int? fabricationCost = null;
|
int? fabricationCost = null;
|
||||||
int? deconstructProductCost = null;
|
int? deconstructProductCost = null;
|
||||||
|
|
||||||
@@ -1053,7 +1136,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
foreach (var ingredient in fabricationRecipe.RequiredItems)
|
foreach (var ingredient in fabricationRecipe.RequiredItems)
|
||||||
{
|
{
|
||||||
int? ingredientPrice = ingredient.ItemPrefab.GetPrices()?.Min(p => p.BuyPrice);
|
int? ingredientPrice = ingredient.ItemPrefab.GetMinPrice();
|
||||||
if (ingredientPrice.HasValue)
|
if (ingredientPrice.HasValue)
|
||||||
{
|
{
|
||||||
if (!fabricationCost.HasValue) { fabricationCost = 0; }
|
if (!fabricationCost.HasValue) { fabricationCost = 0; }
|
||||||
@@ -1071,7 +1154,7 @@ namespace Barotrauma
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int? deconstructProductPrice = targetItem.GetPrices()?.Min(p => p.BuyPrice);
|
int? deconstructProductPrice = targetItem.GetMinPrice();
|
||||||
if (deconstructProductPrice.HasValue)
|
if (deconstructProductPrice.HasValue)
|
||||||
{
|
{
|
||||||
if (!deconstructProductCost.HasValue) { deconstructProductCost = 0; }
|
if (!deconstructProductCost.HasValue) { deconstructProductCost = 0; }
|
||||||
@@ -1300,7 +1383,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
commands.Add(new Command("eventstats", "", (string[] args) =>
|
commands.Add(new Command("eventstats", "", (string[] args) =>
|
||||||
{
|
{
|
||||||
var debugLines = ScriptedEventSet.GetDebugStatistics();
|
var debugLines = EventSet.GetDebugStatistics();
|
||||||
string filePath = "eventstats.txt";
|
string filePath = "eventstats.txt";
|
||||||
File.WriteAllLines(filePath, debugLines);
|
File.WriteAllLines(filePath, debugLines);
|
||||||
ToolBox.OpenFileWithShell(Path.GetFullPath(filePath));
|
ToolBox.OpenFileWithShell(Path.GetFullPath(filePath));
|
||||||
@@ -1537,6 +1620,76 @@ namespace Barotrauma
|
|||||||
File.WriteAllLines(filePath, lines);
|
File.WriteAllLines(filePath, lines);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
commands.Add(new Command("dumpeventtexts", "dumpeventtexts [filepath]: gets the texts from event files and and writes them into a file along with xml tags that can be used in translation files. If the filepath is omitted, the file is written to Content/Texts/EventTexts.txt", (string[] args) =>
|
||||||
|
{
|
||||||
|
string filePath = args.Length > 0 ? args[0] : "Content/Texts/EventTexts.txt";
|
||||||
|
List<string> lines = new List<string>();
|
||||||
|
HashSet<XDocument> docs = new HashSet<XDocument>();
|
||||||
|
HashSet<string> textIds = new HashSet<string>();
|
||||||
|
|
||||||
|
foreach (EventPrefab eventPrefab in EventSet.GetAllEventPrefabs())
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(eventPrefab.Identifier))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
docs.Add(eventPrefab.ConfigElement.Document);
|
||||||
|
getTextsFromElement(eventPrefab.ConfigElement, lines, eventPrefab.Identifier);
|
||||||
|
}
|
||||||
|
File.WriteAllLines(filePath, lines);
|
||||||
|
|
||||||
|
ToolBox.OpenFileWithShell(Path.GetFullPath(filePath));
|
||||||
|
|
||||||
|
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings
|
||||||
|
{
|
||||||
|
Indent = true,
|
||||||
|
NewLineOnAttributes = false
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (XDocument doc in docs)
|
||||||
|
{
|
||||||
|
using (var writer = XmlWriter.Create(new System.Uri(doc.BaseUri).LocalPath, settings))
|
||||||
|
{
|
||||||
|
doc.WriteTo(writer);
|
||||||
|
writer.Flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void getTextsFromElement(XElement element, List<string> list, string parentName)
|
||||||
|
{
|
||||||
|
string text = element.GetAttributeString("text", null);
|
||||||
|
string textId = $"EventText.{parentName}";
|
||||||
|
if (!string.IsNullOrEmpty(text) && !text.Contains("EventText.", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
list.Add($"<{textId}>{text}</{textId}>");
|
||||||
|
element.SetAttributeValue("text", textId);
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 1;
|
||||||
|
foreach (XElement subElement in element.Elements())
|
||||||
|
{
|
||||||
|
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||||
|
{
|
||||||
|
case "conversationaction":
|
||||||
|
while (textIds.Contains(parentName+".c"+i))
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
parentName += ".c" + i;
|
||||||
|
break;
|
||||||
|
case "option":
|
||||||
|
while (textIds.Contains(parentName.Substring(0, parentName.Length - 3) + ".o" + i))
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
parentName = parentName.Substring(0, parentName.Length - 3) + ".o" + i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
textIds.Add(parentName);
|
||||||
|
getTextsFromElement(subElement, list, parentName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
commands.Add(new Command("itemcomponentdocumentation", "", (string[] args) =>
|
commands.Add(new Command("itemcomponentdocumentation", "", (string[] args) =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,365 @@
|
|||||||
|
using Barotrauma.Networking;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using Barotrauma.Extensions;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
partial class ConversationAction : EventAction
|
||||||
|
{
|
||||||
|
private GUIMessageBox dialogBox;
|
||||||
|
|
||||||
|
private static ConversationAction lastActiveAction;
|
||||||
|
private static GUIMessageBox lastMessageBox;
|
||||||
|
|
||||||
|
public static bool IsDialogOpen
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return GUIMessageBox.MessageBoxes.Any(mb =>
|
||||||
|
mb.UserData as string == "ConversationAction" ||
|
||||||
|
(mb.UserData is Pair<string, UInt16> pair && pair.First == "ConversationAction"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static bool FadeScreenToBlack
|
||||||
|
{
|
||||||
|
get { return IsDialogOpen && shouldFadeToBlack; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool shouldFadeToBlack;
|
||||||
|
|
||||||
|
private bool IsBlockedByAnotherConversation(IEnumerable<Entity> _)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
lastActiveAction != null &&
|
||||||
|
lastActiveAction.ParentEvent != ParentEvent &&
|
||||||
|
Timing.TotalTime < lastActiveAction.lastActiveTime + BlockOtherConversationsDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
partial void ShowDialog(Character speaker, Character targetCharacter)
|
||||||
|
{
|
||||||
|
CreateDialog(Text, speaker, Options.Select(opt => opt.Text), GetEndingOptions(), actionInstance: this, spriteIdentifier: EventSprite, fadeToBlack: FadeToBlack, dialogType: DialogType, continueConversation: ContinueConversation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CreateDialog(string text, Character speaker, IEnumerable<string> options, int[] closingOptions, string eventSprite, UInt16 actionId, bool fadeToBlack, DialogTypes dialogType, bool continueConversation = false)
|
||||||
|
{
|
||||||
|
CreateDialog(text, speaker, options, closingOptions, actionInstance: null, actionId: actionId, spriteIdentifier: eventSprite, fadeToBlack: fadeToBlack, dialogType: dialogType, continueConversation: continueConversation);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CreateDialog(string text, Character speaker, IEnumerable<string> options, int[] closingOptions, string spriteIdentifier = null,
|
||||||
|
ConversationAction actionInstance = null, UInt16? actionId = null, bool fadeToBlack = false, DialogTypes dialogType = DialogTypes.Regular, bool continueConversation = false)
|
||||||
|
{
|
||||||
|
Debug.Assert(actionInstance == null || actionId == null);
|
||||||
|
|
||||||
|
shouldFadeToBlack = fadeToBlack;
|
||||||
|
|
||||||
|
if (lastMessageBox != null && !lastMessageBox.Closed && GUIMessageBox.MessageBoxes.Contains(lastMessageBox))
|
||||||
|
{
|
||||||
|
if (actionId != null && lastMessageBox.UserData is Pair<string, ushort> userData)
|
||||||
|
{
|
||||||
|
if (userData.Second == actionId) { return; }
|
||||||
|
lastMessageBox.UserData = new Pair<string, ushort>("ConversationAction", actionId.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
GUIListBox conversationList = lastMessageBox.FindChild("conversationlist", true) as GUIListBox;
|
||||||
|
Debug.Assert(conversationList != null);
|
||||||
|
|
||||||
|
// gray out the last text block
|
||||||
|
if (conversationList.Content.Children.LastOrDefault() is GUILayoutGroup lastElement)
|
||||||
|
{
|
||||||
|
if (lastElement.FindChild("text", true) is GUITextBlock textLayout)
|
||||||
|
{
|
||||||
|
textLayout.OverrideTextColor(Color.DarkGray * 0.8f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<GUIButton> extraButtons = CreateConversation(conversationList, text, speaker, options, string.IsNullOrWhiteSpace(spriteIdentifier));
|
||||||
|
AssignActionsToButtons(extraButtons, lastMessageBox);
|
||||||
|
RecalculateLastMessage(conversationList, true);
|
||||||
|
|
||||||
|
conversationList.ScrollToEnd(0.5f);
|
||||||
|
lastMessageBox.SetBackgroundIcon(EventSet.GetEventSprite(spriteIdentifier));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var (relative, min) = GetSizes(dialogType);
|
||||||
|
|
||||||
|
GUIMessageBox messageBox = new GUIMessageBox(string.Empty, string.Empty, new string[0],
|
||||||
|
relativeSize: relative, minSize: min,
|
||||||
|
type: GUIMessageBox.Type.InGame, backgroundIcon: EventSet.GetEventSprite(spriteIdentifier))
|
||||||
|
{
|
||||||
|
UserData = "ConversationAction"
|
||||||
|
};
|
||||||
|
|
||||||
|
lastMessageBox = messageBox;
|
||||||
|
|
||||||
|
messageBox.InnerFrame.ClearChildren();
|
||||||
|
messageBox.AutoClose = false;
|
||||||
|
GUI.Style.Apply(messageBox.InnerFrame, "DialogBox");
|
||||||
|
|
||||||
|
if (actionInstance != null)
|
||||||
|
{
|
||||||
|
lastActiveAction = actionInstance;
|
||||||
|
actionInstance.dialogBox = messageBox;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
messageBox.UserData = new Pair<string, UInt16>("ConversationAction", actionId.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int padding = GUI.IntScale(16);
|
||||||
|
|
||||||
|
GUIListBox listBox = new GUIListBox(new RectTransform(messageBox.InnerFrame.Rect.Size - new Point(padding * 2), messageBox.InnerFrame.RectTransform, Anchor.Center), style: null)
|
||||||
|
{
|
||||||
|
KeepSpaceForScrollBar = true,
|
||||||
|
HoverCursor = CursorState.Default,
|
||||||
|
UserData = "conversationlist"
|
||||||
|
};
|
||||||
|
|
||||||
|
List<GUIButton> buttons = CreateConversation(listBox, text, speaker, options, string.IsNullOrWhiteSpace(spriteIdentifier));
|
||||||
|
AssignActionsToButtons(buttons, messageBox);
|
||||||
|
RecalculateLastMessage(listBox, false);
|
||||||
|
|
||||||
|
messageBox.InnerFrame.RectTransform.MinSize = new Point(0, Math.Max(listBox.RectTransform.MinSize.Y + padding * 2, (int)(100 * GUI.yScale)));
|
||||||
|
|
||||||
|
var shadow = new GUIFrame(new RectTransform(messageBox.InnerFrame.Rect.Size + new Point(padding * 4), messageBox.InnerFrame.RectTransform, Anchor.Center), style: "OuterGlow")
|
||||||
|
{
|
||||||
|
Color = Color.Black * 0.7f
|
||||||
|
};
|
||||||
|
shadow.SetAsFirstChild();
|
||||||
|
|
||||||
|
void RecalculateLastMessage(GUIListBox conversationList, bool append)
|
||||||
|
{
|
||||||
|
if (conversationList.Content.Children.LastOrDefault() is GUILayoutGroup lastElement)
|
||||||
|
{
|
||||||
|
GUILayoutGroup textLayout = lastElement.GetChild<GUILayoutGroup>();
|
||||||
|
if (lastElement.Rect.Size.Y < textLayout.Rect.Size.Y && !append)
|
||||||
|
{
|
||||||
|
lastElement.RectTransform.MinSize = textLayout.Rect.Size;
|
||||||
|
}
|
||||||
|
if (textLayout != null)
|
||||||
|
{
|
||||||
|
int textHeight = textLayout.Children.Sum(c => c.Rect.Height);
|
||||||
|
textLayout.RectTransform.MaxSize = new Point(lastElement.RectTransform.MaxSize.X, textHeight);
|
||||||
|
textLayout.Recalculate();
|
||||||
|
}
|
||||||
|
int sumHeight = lastElement.Children.Sum(c => c.Rect.Height);
|
||||||
|
lastElement.RectTransform.MaxSize = new Point(lastElement.RectTransform.MaxSize.X, sumHeight);
|
||||||
|
lastElement.Recalculate();
|
||||||
|
conversationList.RecalculateChildren();
|
||||||
|
|
||||||
|
if (!append || textLayout == null) { return; }
|
||||||
|
|
||||||
|
foreach (GUIComponent child in textLayout.Children)
|
||||||
|
{
|
||||||
|
conversationList.UpdateScrollBarSize();
|
||||||
|
float wait = conversationList.BarSize < 1.0f ? 0.5f : 0.0f;
|
||||||
|
|
||||||
|
if (child is GUITextBlock) { child.FadeIn(wait, 0.5f); }
|
||||||
|
|
||||||
|
if (child is GUIButton btn)
|
||||||
|
{
|
||||||
|
btn.FadeIn(wait, 1.0f);
|
||||||
|
btn.TextBlock.FadeIn(wait, 0.5f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssignActionsToButtons(List<GUIButton> optionButtons, GUIMessageBox target)
|
||||||
|
{
|
||||||
|
if (!options.Any())
|
||||||
|
{
|
||||||
|
GUIButton closeButton = new GUIButton(new RectTransform(Vector2.One, target.InnerFrame.RectTransform, Anchor.BottomRight, scaleBasis: ScaleBasis.Smallest)
|
||||||
|
{
|
||||||
|
MaxSize = new Point(GUI.IntScale(24)),
|
||||||
|
MinSize = new Point(24),
|
||||||
|
AbsoluteOffset = new Point(GUI.IntScale(48), GUI.IntScale(16))
|
||||||
|
}, style: "GUIButtonVerticalArrow")
|
||||||
|
{
|
||||||
|
UserData = "ContinueButton",
|
||||||
|
IgnoreLayoutGroups = true,
|
||||||
|
Bounce = true,
|
||||||
|
OnClicked = (btn, userdata) =>
|
||||||
|
{
|
||||||
|
if (actionInstance != null)
|
||||||
|
{
|
||||||
|
actionInstance.selectedOption = 0;
|
||||||
|
}
|
||||||
|
else if (actionId.HasValue)
|
||||||
|
{
|
||||||
|
SendResponse(actionId.Value, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!continueConversation)
|
||||||
|
{
|
||||||
|
target.Close();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
btn.Frame.FadeOut(0.33f, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
closeButton.Children.ForEach(child => child.SpriteEffects = SpriteEffects.FlipVertically);
|
||||||
|
closeButton.Frame.FadeIn(0.5f, 0.5f);
|
||||||
|
closeButton.SlideIn(0.5f, 0.33f, 16, SlideDirection.Down);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < optionButtons.Count; i++)
|
||||||
|
{
|
||||||
|
optionButtons[i].UserData = i;
|
||||||
|
optionButtons[i].OnClicked += (btn, userdata) =>
|
||||||
|
{
|
||||||
|
int selectedOption = (userdata as int?) ?? 0;
|
||||||
|
if (actionInstance != null)
|
||||||
|
{
|
||||||
|
actionInstance.selectedOption = selectedOption;
|
||||||
|
foreach (GUIButton otherButton in optionButtons)
|
||||||
|
{
|
||||||
|
otherButton.CanBeFocused = false;
|
||||||
|
if (otherButton != btn)
|
||||||
|
{
|
||||||
|
otherButton.TextBlock.OverrideTextColor(Color.DarkGray * 0.8f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
btn.ExternalHighlight = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actionId.HasValue)
|
||||||
|
{
|
||||||
|
SendResponse(actionId.Value, selectedOption);
|
||||||
|
btn.CanBeFocused = false;
|
||||||
|
btn.ExternalHighlight = true;
|
||||||
|
foreach (GUIButton otherButton in optionButtons)
|
||||||
|
{
|
||||||
|
otherButton.CanBeFocused = false;
|
||||||
|
if (otherButton != btn)
|
||||||
|
{
|
||||||
|
otherButton.TextBlock.OverrideTextColor(Color.DarkGray * 0.8f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//should not happen
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (closingOptions.Contains(i)) { optionButtons[i].OnClicked += target.Close; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Tuple<Vector2, Point> GetSizes(DialogTypes dialogTypes)
|
||||||
|
{
|
||||||
|
return dialogTypes switch
|
||||||
|
{
|
||||||
|
DialogTypes.Regular => Tuple.Create(new Vector2(0.3f, 0.2f), new Point(512, 256)),
|
||||||
|
_ => Tuple.Create(new Vector2(0.3f, 0.15f), new Point(512, 128))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<GUIButton> CreateConversation(GUIListBox parentBox, string text, Character speaker, IEnumerable<string> options, bool drawChathead = true)
|
||||||
|
{
|
||||||
|
var content = new GUILayoutGroup(new RectTransform(Vector2.One, parentBox.Content.RectTransform), childAnchor: Anchor.CenterLeft, isHorizontal: true)
|
||||||
|
{
|
||||||
|
Stretch = true,
|
||||||
|
CanBeFocused = true,
|
||||||
|
AlwaysOverrideCursor = true
|
||||||
|
};
|
||||||
|
|
||||||
|
string translatedText = TextManager.Get(text, returnNull: true) ?? text;
|
||||||
|
|
||||||
|
if (speaker?.Info != null && drawChathead)
|
||||||
|
{
|
||||||
|
// chathead
|
||||||
|
new GUICustomComponent(new RectTransform(new Vector2(0.15f, 0.8f), content.RectTransform), onDraw: (sb, customComponent) =>
|
||||||
|
{
|
||||||
|
speaker.Info.DrawIcon(sb, customComponent.Rect.Center.ToVector2(), customComponent.Rect.Size.ToVector2());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var textContent = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), content.RectTransform), childAnchor: Anchor.TopCenter)
|
||||||
|
{
|
||||||
|
AbsoluteSpacing = GUI.IntScale(5)
|
||||||
|
};
|
||||||
|
|
||||||
|
var textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), textContent.RectTransform), translatedText, wrap: true)
|
||||||
|
{
|
||||||
|
AlwaysOverrideCursor = true,
|
||||||
|
UserData = "text"
|
||||||
|
};
|
||||||
|
|
||||||
|
List<GUIButton> buttons = new List<GUIButton>();
|
||||||
|
if (options.Any())
|
||||||
|
{
|
||||||
|
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");
|
||||||
|
btn.TextBlock.TextAlignment = Alignment.CenterLeft;
|
||||||
|
btn.TextColor = btn.HoverTextColor = GUI.Style.Green;
|
||||||
|
btn.TextBlock.Wrap = true;
|
||||||
|
buttons.Add(btn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
content.Recalculate();
|
||||||
|
textContent.Recalculate();
|
||||||
|
textBlock.CalculateHeightFromText();
|
||||||
|
textBlock.RectTransform.MinSize = new Point(0, (int)(textBlock.Rect.Height * 1.2f));
|
||||||
|
foreach (GUIButton btn in buttons)
|
||||||
|
{
|
||||||
|
btn.TextBlock.SetTextPos();
|
||||||
|
btn.TextBlock.CalculateHeightFromText();
|
||||||
|
btn.RectTransform.MinSize = new Point(0, (int)(btn.TextBlock.Rect.Height * 1.2f));
|
||||||
|
}
|
||||||
|
|
||||||
|
textContent.RectTransform.MinSize = new Point(0, textContent.Children.Sum(c => c.Rect.Height + textContent.AbsoluteSpacing) + GUI.IntScale(16));
|
||||||
|
// content.RectTransform.MinSize = new Point(0, textContent.Rect.Height);
|
||||||
|
|
||||||
|
return buttons;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SendResponse(UInt16 actionId, int selectedOption)
|
||||||
|
{
|
||||||
|
IWriteMessage outmsg = new WriteOnlyMessage();
|
||||||
|
outmsg.Write((byte)ClientPacketHeader.EVENTMANAGER_RESPONSE);
|
||||||
|
outmsg.Write(actionId);
|
||||||
|
outmsg.Write((byte)selectedOption);
|
||||||
|
GameMain.Client?.ClientPeer?.Send(outmsg, DeliveryMethod.Reliable);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Too broken, left it here if I ever want to come back to it
|
||||||
|
private static List<RichTextData> GetQuoteHighlights(string text, Color color)
|
||||||
|
{
|
||||||
|
char[] quotes = { '“', '”', '\"', '\'', '「', '」'};
|
||||||
|
|
||||||
|
List<RichTextData> textColors = new List<RichTextData> { new RichTextData { StartIndex = 0 } };
|
||||||
|
bool start = true;
|
||||||
|
for (int i = 0; i < text.Length; i++)
|
||||||
|
{
|
||||||
|
char c = text[i];
|
||||||
|
if (quotes.Contains(c))
|
||||||
|
{
|
||||||
|
textColors.Last().EndIndex = i - 1;
|
||||||
|
textColors.Add(new RichTextData { StartIndex = i, Color = start ? color : (Color?) null });
|
||||||
|
start = !start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (textColors.LastOrDefault() is { } last && last.EndIndex == 0)
|
||||||
|
{
|
||||||
|
last.EndIndex = text.Length;
|
||||||
|
}
|
||||||
|
return textColors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,12 @@
|
|||||||
using Microsoft.Xna.Framework;
|
#nullable enable
|
||||||
|
using Barotrauma.Extensions;
|
||||||
|
using Barotrauma.Networking;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -11,31 +17,40 @@ namespace Barotrauma
|
|||||||
private float intensityGraphUpdateInterval;
|
private float intensityGraphUpdateInterval;
|
||||||
private float lastIntensityUpdate;
|
private float lastIntensityUpdate;
|
||||||
|
|
||||||
|
private Event? pinnedEvent;
|
||||||
|
private Vector2 pinnedPosition = new Vector2(256, 128);
|
||||||
|
private bool isDragging;
|
||||||
|
|
||||||
public void DebugDraw(SpriteBatch spriteBatch)
|
public void DebugDraw(SpriteBatch spriteBatch)
|
||||||
{
|
{
|
||||||
foreach (ScriptedEvent ev in activeEvents)
|
foreach (Event ev in activeEvents)
|
||||||
{
|
{
|
||||||
Vector2 drawPos = ev.DebugDrawPos;
|
Vector2 drawPos = ev.DebugDrawPos;
|
||||||
drawPos.Y = -drawPos.Y;
|
drawPos.Y = -drawPos.Y;
|
||||||
|
|
||||||
var textOffset = new Vector2(-150, 0);
|
var textOffset = new Vector2(-150, 0);
|
||||||
ShapeExtensions.DrawCircle(spriteBatch, drawPos, 600, 6, Color.White, thickness: 20);
|
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, GUI.LargeFont);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DebugDrawHUD(SpriteBatch spriteBatch, int y)
|
public void DebugDrawHUD(SpriteBatch spriteBatch, int y)
|
||||||
{
|
{
|
||||||
|
foreach (ScriptedEvent scriptedEvent in activeEvents.Where(ev => !ev.IsFinished && ev is ScriptedEvent).Cast<ScriptedEvent>())
|
||||||
|
{
|
||||||
|
DrawEventTargetTags(spriteBatch, scriptedEvent);
|
||||||
|
}
|
||||||
|
|
||||||
GUI.DrawString(spriteBatch, new Vector2(10, y), "EventManager", Color.White, Color.Black * 0.6f, 0, GUI.SmallFont);
|
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: " + eventCoolDown, Color.White, Color.Black * 0.6f, 0, GUI.SmallFont);
|
GUI.DrawString(spriteBatch, new Vector2(15, y + 20), "Event cooldown: " + eventCoolDown, 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 + 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(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(15, y + 65), "AvgHealth: " + (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 + 65), "AvgHealth: " + (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), "AvgHullIntegrity: " + (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 + 80), "AvgHullIntegrity: " + (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), "FloodingAmount: " + (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 + 95), "FloodingAmount: " + (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), "FireAmount: " + (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 + 110), "FireAmount: " + (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), "EnemyDanger: " + (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 + 125), "EnemyDanger: " + (int) Math.Round(enemyDanger * 100), Color.Lerp(GUI.Style.Green, GUI.Style.Red, enemyDanger), Color.Black * 0.6f, 0, GUI.SmallFont);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
if (PlayerInput.KeyDown(Microsoft.Xna.Framework.Input.Keys.LeftAlt) &&
|
if (PlayerInput.KeyDown(Microsoft.Xna.Framework.Input.Keys.LeftAlt) &&
|
||||||
@@ -56,7 +71,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
intensityGraph.Update(currentIntensity);
|
intensityGraph.Update(currentIntensity);
|
||||||
targetIntensityGraph.Update(targetIntensity);
|
targetIntensityGraph.Update(targetIntensity);
|
||||||
lastIntensityUpdate = (float)Timing.TotalTime;
|
lastIntensityUpdate = (float) Timing.TotalTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle graphRect = new Rectangle(15, y + 150, 150, 50);
|
Rectangle graphRect = new Rectangle(15, y + 150, 150, 50);
|
||||||
@@ -72,20 +87,19 @@ namespace Barotrauma
|
|||||||
y = graphRect.Bottom + 20;
|
y = graphRect.Bottom + 20;
|
||||||
if (eventCoolDown > 0.0f)
|
if (eventCoolDown > 0.0f)
|
||||||
{
|
{
|
||||||
GUI.DrawString(spriteBatch, new Vector2(graphRect.X, y), "Event cooldown active: " + (int)eventCoolDown, Color.LightGreen * 0.8f, null, 0, GUI.SmallFont);
|
GUI.DrawString(spriteBatch, new Vector2(graphRect.X, y), "Event cooldown active: " + (int) eventCoolDown, Color.LightGreen * 0.8f, null, 0, GUI.SmallFont);
|
||||||
y += 15;
|
y += 15;
|
||||||
}
|
}
|
||||||
else if (currentIntensity > eventThreshold)
|
else if (currentIntensity > eventThreshold)
|
||||||
{
|
{
|
||||||
GUI.DrawString(spriteBatch, new Vector2(graphRect.X, y),
|
GUI.DrawString(spriteBatch, new Vector2(graphRect.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, GUI.SmallFont);
|
||||||
y += 15;
|
y += 15;
|
||||||
}
|
}
|
||||||
foreach (ScriptedEventSet eventSet in pendingEventSets)
|
|
||||||
|
foreach (EventSet eventSet in pendingEventSets)
|
||||||
{
|
{
|
||||||
float distanceTraveled = MathHelper.Clamp(
|
if (Submarine.MainSub == null) { break; }
|
||||||
(Submarine.MainSub.WorldPosition.X - level.StartPosition.X) / (level.EndPosition.X - level.StartPosition.X),
|
|
||||||
0.0f, 1.0f);
|
|
||||||
|
|
||||||
GUI.DrawString(spriteBatch, new Vector2(graphRect.X, y), "New event (ID " + eventSet.DebugIdentifier + ") after: ", Color.Orange * 0.8f, null, 0, GUI.SmallFont);
|
GUI.DrawString(spriteBatch, new Vector2(graphRect.X, y), "New event (ID " + eventSet.DebugIdentifier + ") after: ", Color.Orange * 0.8f, null, 0, GUI.SmallFont);
|
||||||
y += 12;
|
y += 12;
|
||||||
@@ -94,35 +108,420 @@ namespace Barotrauma
|
|||||||
roundDuration < eventSet.MinMissionTime)
|
roundDuration < eventSet.MinMissionTime)
|
||||||
{
|
{
|
||||||
GUI.DrawString(spriteBatch, new Vector2(graphRect.X, y),
|
GUI.DrawString(spriteBatch, new Vector2(graphRect.X, y),
|
||||||
" " + (int)(eventSet.MinDistanceTraveled * 100.0f) + "% travelled (current: " + (int)(distanceTraveled * 100.0f) + " %)",
|
" " + (int) (eventSet.MinDistanceTraveled * 100.0f) + "% travelled (current: " + (int) (distanceTraveled * 100.0f) + " %)",
|
||||||
Color.Orange * 0.8f, null, 0, GUI.SmallFont);
|
Color.Orange * 0.8f, null, 0, GUI.SmallFont);
|
||||||
y += 12;
|
y += 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CurrentIntensity < eventSet.MinIntensity || CurrentIntensity > eventSet.MaxIntensity)
|
if (CurrentIntensity < eventSet.MinIntensity || CurrentIntensity > eventSet.MaxIntensity)
|
||||||
{
|
{
|
||||||
GUI.DrawString(spriteBatch, new Vector2(graphRect.X, y),
|
GUI.DrawString(spriteBatch, new Vector2(graphRect.X, y),
|
||||||
" intensity between " + ((int)eventSet.MinIntensity) + " and " + ((int)eventSet.MaxIntensity),
|
" intensity between " + ((int) eventSet.MinIntensity) + " and " + ((int) eventSet.MaxIntensity),
|
||||||
Color.Orange * 0.8f, null, 0, GUI.SmallFont);
|
Color.Orange * 0.8f, null, 0, GUI.SmallFont);
|
||||||
y += 12;
|
y += 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (roundDuration < eventSet.MinMissionTime)
|
if (roundDuration < eventSet.MinMissionTime)
|
||||||
{
|
{
|
||||||
GUI.DrawString(spriteBatch, new Vector2(graphRect.X, y),
|
GUI.DrawString(spriteBatch, new Vector2(graphRect.X, y),
|
||||||
" " + (int)(eventSet.MinMissionTime - roundDuration) + " s",
|
" " + (int) (eventSet.MinMissionTime - roundDuration) + " s",
|
||||||
Color.Orange * 0.8f, null, 0, GUI.SmallFont);
|
Color.Orange * 0.8f, null, 0, GUI.SmallFont);
|
||||||
}
|
}
|
||||||
|
|
||||||
y += 15;
|
y += 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GUI.DrawString(spriteBatch, new Vector2(graphRect.X, y), "Current events: ", Color.White * 0.9f, null, 0, GUI.SmallFont);
|
GUI.DrawString(spriteBatch, new Vector2(graphRect.X, y), "Current events: ", Color.White * 0.9f, null, 0, GUI.SmallFont);
|
||||||
y += 12;
|
y += 15;
|
||||||
foreach (ScriptedEvent scriptedEvent in activeEvents)
|
|
||||||
|
foreach (Event ev in activeEvents.Where(ev => !ev.IsFinished || PlayerInput.IsShiftDown()))
|
||||||
{
|
{
|
||||||
if (scriptedEvent.IsFinished) { continue; }
|
GUI.DrawString(spriteBatch, new Vector2(graphRect.X + 5, y), ev.ToString(), (!ev.IsFinished ? Color.White : Color.Red) * 0.8f, null, 0, GUI.SmallFont);
|
||||||
GUI.DrawString(spriteBatch, new Vector2(graphRect.X + 5, y), scriptedEvent.ToString(), Color.White * 0.8f, null, 0, GUI.SmallFont);
|
|
||||||
y += 12;
|
Rectangle rect = new Rectangle(new Point(graphRect.X + 5, y), GUI.SmallFont.MeasureString(ev.ToString()).ToPoint());
|
||||||
|
|
||||||
|
Rectangle outlineRect = new Rectangle(rect.Location, rect.Size);
|
||||||
|
outlineRect.Inflate(4, 4);
|
||||||
|
|
||||||
|
if (pinnedEvent == ev) { GUI.DrawRectangle(spriteBatch, outlineRect, Color.White); }
|
||||||
|
|
||||||
|
if (rect.Contains(PlayerInput.MousePosition))
|
||||||
|
{
|
||||||
|
GUI.MouseCursor = CursorState.Hand;
|
||||||
|
GUI.DrawRectangle(spriteBatch, outlineRect, Color.White);
|
||||||
|
|
||||||
|
if (ev != pinnedEvent)
|
||||||
|
{
|
||||||
|
DrawEvent(spriteBatch, ev, rect);
|
||||||
|
}
|
||||||
|
else if (PlayerInput.SecondaryMouseButtonHeld() || PlayerInput.SecondaryMouseButtonDown())
|
||||||
|
{
|
||||||
|
pinnedEvent = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PlayerInput.PrimaryMouseButtonHeld() || PlayerInput.PrimaryMouseButtonDown())
|
||||||
|
{
|
||||||
|
pinnedEvent = ev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
y += 18;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawPinnedEvent(SpriteBatch spriteBatch)
|
||||||
|
{
|
||||||
|
if (pinnedEvent != null)
|
||||||
|
{
|
||||||
|
Rectangle rect = DrawEvent(spriteBatch, pinnedEvent, null);
|
||||||
|
|
||||||
|
if (rect != Rectangle.Empty)
|
||||||
|
{
|
||||||
|
if (rect.Contains(PlayerInput.MousePosition) && !isDragging)
|
||||||
|
{
|
||||||
|
GUI.MouseCursor = CursorState.Move;
|
||||||
|
if (PlayerInput.PrimaryMouseButtonDown() || PlayerInput.PrimaryMouseButtonHeld())
|
||||||
|
{
|
||||||
|
isDragging = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PlayerInput.SecondaryMouseButtonClicked() || PlayerInput.SecondaryMouseButtonHeld())
|
||||||
|
{
|
||||||
|
pinnedEvent = null;
|
||||||
|
isDragging = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDragging)
|
||||||
|
{
|
||||||
|
GUI.MouseCursor = CursorState.Dragging;
|
||||||
|
pinnedPosition = PlayerInput.MousePosition - (new Vector2(rect.Width / 2.0f, -24));
|
||||||
|
if (!PlayerInput.PrimaryMouseButtonHeld())
|
||||||
|
{
|
||||||
|
isDragging = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DrawEventTargetTags(SpriteBatch spriteBatch, ScriptedEvent scriptedEvent)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
foreach (Entity entity in value)
|
||||||
|
{
|
||||||
|
if (tagsDictionary.ContainsKey(entity))
|
||||||
|
{
|
||||||
|
tagsDictionary[entity].Add(key);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tagsDictionary.Add(entity, new List<string> { key });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string identifier = scriptedEvent.Prefab.Identifier;
|
||||||
|
|
||||||
|
foreach ((Entity entity, List<string> 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}"; }
|
||||||
|
|
||||||
|
List<RichTextData> richTextData = RichTextData.GetRichTextData(text, out text);
|
||||||
|
|
||||||
|
Vector2 entityPos = cam.WorldToScreen(entity.WorldPosition);
|
||||||
|
Vector2 infoSize = GUI.SmallFont.MeasureString(text);
|
||||||
|
|
||||||
|
Vector2 infoPos = entityPos + new Vector2(128 * cam.Zoom, -(128 * cam.Zoom));
|
||||||
|
infoPos.Y -= infoSize.Y / 2;
|
||||||
|
|
||||||
|
Rectangle infoRect = new Rectangle(infoPos.ToPoint(), infoSize.ToPoint());
|
||||||
|
infoRect.Inflate(4, 4);
|
||||||
|
|
||||||
|
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.DrawLine(spriteBatch, entityPos, new Vector2(infoRect.Location.X, infoRect.Location.Y + infoRect.Height / 2), Color.White);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly struct DebugLine
|
||||||
|
{
|
||||||
|
public readonly Vector2 Position;
|
||||||
|
public readonly Color Color;
|
||||||
|
|
||||||
|
public DebugLine(Vector2 position, Color color)
|
||||||
|
{
|
||||||
|
Position = position;
|
||||||
|
Color = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Rectangle DrawEvent(SpriteBatch spriteBatch, Event ev, Rectangle? parentRect = null)
|
||||||
|
{
|
||||||
|
return ev switch
|
||||||
|
{
|
||||||
|
ScriptedEvent scriptedEvent => DrawScriptedEvent(spriteBatch, scriptedEvent, parentRect),
|
||||||
|
ArtifactEvent artifactEvent => DrawArtifactEvent(spriteBatch, artifactEvent, parentRect),
|
||||||
|
MonsterEvent monsterEvent => DrawMonsterEvent(spriteBatch, monsterEvent, parentRect),
|
||||||
|
_ => Rectangle.Empty
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private Rectangle DrawScriptedEvent(SpriteBatch spriteBatch, ScriptedEvent scriptedEvent, Rectangle? parentRect = null)
|
||||||
|
{
|
||||||
|
EventAction? currentEvent = !scriptedEvent.IsFinished ? scriptedEvent.Actions[scriptedEvent.CurrentActionIndex] : null;
|
||||||
|
|
||||||
|
List<DebugLine> positions = new List<DebugLine>();
|
||||||
|
|
||||||
|
string text = $"Finished: {scriptedEvent.IsFinished.ColorizeObject()}\n" +
|
||||||
|
$"Action index: {scriptedEvent.CurrentActionIndex.ColorizeObject()}\n" +
|
||||||
|
$"Current action: {currentEvent?.ToDebugString() ?? ToolBox.ColorizeObject(null)}\n";
|
||||||
|
|
||||||
|
text += "All actions:\n";
|
||||||
|
text += FindActions(scriptedEvent).Aggregate(string.Empty, (current, action) => current + $"{new string(' ', action.Item1 * 6)}{action.Item2.ToDebugString()}\n");
|
||||||
|
|
||||||
|
text += "Targets:\n";
|
||||||
|
foreach (var (key, value) in scriptedEvent.Targets)
|
||||||
|
{
|
||||||
|
text += $" {key.ColorizeObject()}: {value.Aggregate(string.Empty, (current, entity) => current + $"{entity.ColorizeObject()} ")}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scriptedEvent.Targets != null)
|
||||||
|
{
|
||||||
|
foreach ((_, List<Entity> entities) in scriptedEvent.Targets)
|
||||||
|
{
|
||||||
|
if (entities == null || !entities.Any()) { continue; }
|
||||||
|
|
||||||
|
foreach (var entity in entities)
|
||||||
|
{
|
||||||
|
positions.Add(new DebugLine(entity.WorldPosition, Color.White));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return DrawInfoRectangle(spriteBatch, scriptedEvent, text, parentRect, positions);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Rectangle DrawArtifactEvent(SpriteBatch spriteBatch, ArtifactEvent artifactEvent, Rectangle? parentRect = null)
|
||||||
|
{
|
||||||
|
List<DebugLine> positions = new List<DebugLine>();
|
||||||
|
|
||||||
|
string text = $"Finished: {artifactEvent.IsFinished.ColorizeObject()}\n" +
|
||||||
|
$"Item: {artifactEvent.Item.ColorizeObject()}\n" +
|
||||||
|
$"Spawn pending: {artifactEvent.SpawnPending.ColorizeObject()}\n" +
|
||||||
|
$"Spawn position: {artifactEvent.SpawnPos.ColorizeObject()}\n";
|
||||||
|
|
||||||
|
if (artifactEvent.Item != null)
|
||||||
|
{
|
||||||
|
Vector2 pos = artifactEvent.Item.WorldPosition;
|
||||||
|
positions.Add(new DebugLine(pos, Color.White));
|
||||||
|
}
|
||||||
|
|
||||||
|
return DrawInfoRectangle(spriteBatch, artifactEvent, text, parentRect, positions);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Rectangle DrawMonsterEvent(SpriteBatch spriteBatch, MonsterEvent monsterEvent, Rectangle? parentRect = null)
|
||||||
|
{
|
||||||
|
List<DebugLine> positions = new List<DebugLine>();
|
||||||
|
|
||||||
|
string text = $"Finished: {monsterEvent.IsFinished.ColorizeObject()}\n" +
|
||||||
|
$"Amount: {monsterEvent.MinAmount.ColorizeObject()} - {monsterEvent.MaxAmount.ColorizeObject()}\n" +
|
||||||
|
$"Spawn pending: {monsterEvent.SpawnPending.ColorizeObject()}\n" +
|
||||||
|
$"Spawn position: {monsterEvent.SpawnPos.ColorizeObject()}\n";
|
||||||
|
|
||||||
|
if (monsterEvent.SpawnPos != null && Submarine.MainSub != null)
|
||||||
|
{
|
||||||
|
Vector2 pos = monsterEvent.SpawnPos.Value;
|
||||||
|
text += $"Distance from submarine: {Vector2.Distance(pos, Submarine.MainSub.WorldPosition).ColorizeObject()}\n";
|
||||||
|
positions.Add(new DebugLine(pos, Color.White));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (monsterEvent.Monsters != null)
|
||||||
|
{
|
||||||
|
text += !monsterEvent.Monsters.Any() ? $"Monsters: {"None".ColorizeObject()}" : "Monsters:\n";
|
||||||
|
|
||||||
|
foreach (Character monster in monsterEvent.Monsters)
|
||||||
|
{
|
||||||
|
text += $" {monster.ColorizeObject()} -> (Dead: {monster.IsDead.ColorizeObject()}, Health: {monster.HealthPercentage.ColorizeObject()}%, AIState: {(monster.AIController?.State).ColorizeObject()})\n";
|
||||||
|
positions.Add(new DebugLine(monster.WorldPosition, Color.Red));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return DrawInfoRectangle(spriteBatch, monsterEvent, text, parentRect, positions);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Rectangle DrawInfoRectangle(SpriteBatch spriteBatch, Event @event, string text, Rectangle? parentRect = null, List<DebugLine>? drawPoints = null)
|
||||||
|
{
|
||||||
|
text = text.TrimEnd('\r', '\n');
|
||||||
|
|
||||||
|
string identifier = @event.Prefab.Identifier;
|
||||||
|
if (!string.IsNullOrWhiteSpace(identifier))
|
||||||
|
{
|
||||||
|
text = $"Identifier: {identifier.ColorizeObject()}\n{text}";
|
||||||
|
}
|
||||||
|
|
||||||
|
List<RichTextData> richTextData = RichTextData.GetRichTextData(text, out text);
|
||||||
|
|
||||||
|
Vector2 size = GUI.SmallFont.MeasureString(text);
|
||||||
|
Vector2 pos = pinnedPosition;
|
||||||
|
Rectangle infoRect;
|
||||||
|
Rectangle? infoBarRect = null;
|
||||||
|
|
||||||
|
if (parentRect != null)
|
||||||
|
{
|
||||||
|
Rectangle rect = parentRect.Value;
|
||||||
|
pos = new Vector2(350, GameMain.GraphicsHeight / 2.0f - size.Y / 2);
|
||||||
|
infoRect = new Rectangle(pos.ToPoint(), size.ToPoint());
|
||||||
|
infoRect.Inflate(8, 8);
|
||||||
|
|
||||||
|
GUI.DrawLine(spriteBatch, new Vector2(rect.Right, rect.Y + rect.Height / 2), new Vector2(infoRect.X, infoRect.Y + infoRect.Height / 2), Color.White);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
infoRect = new Rectangle(pos.ToPoint(), size.ToPoint());
|
||||||
|
infoRect.Inflate(8, 8);
|
||||||
|
|
||||||
|
Rectangle barRect = new Rectangle(infoRect.Left, infoRect.Top - 32, infoRect.Width, 32);
|
||||||
|
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.DrawRectangle(spriteBatch, barRect, Color.White);
|
||||||
|
infoBarRect = barRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drawPoints != null && drawPoints.Any() && Screen.Selected?.Cam != null)
|
||||||
|
{
|
||||||
|
foreach (DebugLine line in drawPoints)
|
||||||
|
{
|
||||||
|
if (line.Position != Vector2.Zero)
|
||||||
|
{
|
||||||
|
float xPos = infoRect.Right;
|
||||||
|
|
||||||
|
if (parentRect == null && pinnedPosition.X + infoRect.Width / 2.0f > GameMain.GraphicsWidth / 2.0f)
|
||||||
|
{
|
||||||
|
xPos = infoRect.Left;
|
||||||
|
}
|
||||||
|
|
||||||
|
GUI.DrawLine(spriteBatch, new Vector2(xPos, infoRect.Top + infoRect.Height / 2), Screen.Selected.Cam.WorldToScreen(line.Position), line.Color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
return infoBarRect ?? infoRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClientRead(IReadMessage msg)
|
||||||
|
{
|
||||||
|
NetworkEventType eventType = (NetworkEventType)msg.ReadByte();
|
||||||
|
switch (eventType)
|
||||||
|
{
|
||||||
|
case NetworkEventType.STATUSEFFECT:
|
||||||
|
string eventIdentifier = msg.ReadString();
|
||||||
|
UInt16 actionIndex = msg.ReadUInt16();
|
||||||
|
UInt16 targetCount = msg.ReadUInt16();
|
||||||
|
List<Entity> targets = new List<Entity>();
|
||||||
|
for (int i = 0; i < targetCount; i++)
|
||||||
|
{
|
||||||
|
UInt16 targetID = msg.ReadUInt16();
|
||||||
|
Entity target = Entity.FindEntityByID(targetID);
|
||||||
|
if (target != null) { targets.Add(target); }
|
||||||
|
}
|
||||||
|
|
||||||
|
var eventPrefab = EventSet.GetEventPrefab(eventIdentifier);
|
||||||
|
if (eventPrefab == null) { return; }
|
||||||
|
int j = 0;
|
||||||
|
foreach (XElement element in eventPrefab.ConfigElement.Descendants())
|
||||||
|
{
|
||||||
|
if (j != actionIndex)
|
||||||
|
{
|
||||||
|
j++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
foreach (XElement subElement in element.Elements())
|
||||||
|
{
|
||||||
|
if (!subElement.Name.ToString().Equals("statuseffect", StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||||
|
StatusEffect effect = StatusEffect.Load(subElement, $"EventManager.ClientRead ({eventIdentifier})");
|
||||||
|
foreach (Entity target in targets)
|
||||||
|
{
|
||||||
|
effect.Apply(effect.type, 1.0f, target, target as ISerializableEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NetworkEventType.CONVERSATION:
|
||||||
|
UInt16 identifier = msg.ReadUInt16();
|
||||||
|
string eventSprite = msg.ReadString();
|
||||||
|
byte dialogType = msg.ReadByte();
|
||||||
|
bool continueConversation = msg.ReadBoolean();
|
||||||
|
UInt16 speakerId = msg.ReadUInt16();
|
||||||
|
string text = msg.ReadString();
|
||||||
|
bool fadeToBlack = msg.ReadBoolean();
|
||||||
|
byte optionCount = msg.ReadByte();
|
||||||
|
List<string> options = new List<string>();
|
||||||
|
for (int i = 0; i < optionCount; i++)
|
||||||
|
{
|
||||||
|
options.Add(msg.ReadString());
|
||||||
|
}
|
||||||
|
|
||||||
|
byte endCount = msg.ReadByte();
|
||||||
|
int[] endings = new int[endCount];
|
||||||
|
for (int i = 0; i < endCount; i++)
|
||||||
|
{
|
||||||
|
endings[i] = msg.ReadByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(text) && optionCount == 0)
|
||||||
|
{
|
||||||
|
GUIMessageBox.MessageBoxes.ForEachMod(mb =>
|
||||||
|
{
|
||||||
|
if (mb.UserData is Pair<string, UInt16> pair && pair.First == "ConversationAction" && pair.Second == identifier)
|
||||||
|
{
|
||||||
|
(mb as GUIMessageBox)?.Close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ConversationAction.CreateDialog(text, Entity.FindEntityByID(speakerId) as Character, options, endings, eventSprite, identifier, fadeToBlack, (ConversationAction.DialogTypes)dialogType, continueConversation);
|
||||||
|
}
|
||||||
|
if (Entity.FindEntityByID(speakerId) is Character speaker)
|
||||||
|
{
|
||||||
|
speaker.CampaignInteractionType = CampaignMode.InteractionType.None;
|
||||||
|
speaker.SetCustomInteract(null, null);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NetworkEventType.MISSION:
|
||||||
|
string missionIdentifier = msg.ReadString();
|
||||||
|
|
||||||
|
MissionPrefab? prefab = MissionPrefab.List.Find(mp => mp.Identifier.Equals(missionIdentifier, StringComparison.OrdinalIgnoreCase));
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
IconColor = prefab.IconColor
|
||||||
|
};
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
public override void ClientReadInitial(IReadMessage msg)
|
public override void ClientReadInitial(IReadMessage msg)
|
||||||
{
|
{
|
||||||
|
items.Clear();
|
||||||
ushort itemCount = msg.ReadUInt16();
|
ushort itemCount = msg.ReadUInt16();
|
||||||
for (int i = 0; i < itemCount; i++)
|
for (int i = 0; i < itemCount; i++)
|
||||||
{
|
{
|
||||||
@@ -17,7 +18,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
if (items.Count != itemCount)
|
if (items.Count != itemCount)
|
||||||
{
|
{
|
||||||
throw new System.Exception("Error in CargoMission.ClientReadInitial: item count does not match the server count (" + itemCount + " != " + items.Count + "mission: " + Prefab.Identifier + ")");
|
throw new System.Exception("Error in CargoMission.ClientReadInitial: item count does not match the server count (" + itemCount + " != " + items.Count + ", mission: " + Prefab.Identifier + ")");
|
||||||
}
|
}
|
||||||
if (requiredDeliveryAmount == 0) { requiredDeliveryAmount = items.Count; }
|
if (requiredDeliveryAmount == 0) { requiredDeliveryAmount = items.Count; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Barotrauma.Networking;
|
using Barotrauma.Networking;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -13,10 +14,20 @@ namespace Barotrauma
|
|||||||
string header = messageIndex < Headers.Count ? Headers[messageIndex] : "";
|
string header = messageIndex < Headers.Count ? Headers[messageIndex] : "";
|
||||||
string message = messageIndex < Messages.Count ? Messages[messageIndex] : "";
|
string message = messageIndex < Messages.Count ? Messages[messageIndex] : "";
|
||||||
|
|
||||||
|
CoroutineManager.StartCoroutine(ShowMessageBoxAfterRoundSummary(header, message));
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<object> ShowMessageBoxAfterRoundSummary(string header, string message)
|
||||||
|
{
|
||||||
|
while (GUIMessageBox.VisibleBox?.UserData is RoundSummary)
|
||||||
|
{
|
||||||
|
yield return new WaitForSeconds(1.0f);
|
||||||
|
}
|
||||||
new GUIMessageBox(header, message, buttons: new string[0], type: GUIMessageBox.Type.InGame, icon: Prefab.Icon)
|
new GUIMessageBox(header, message, buttons: new string[0], type: GUIMessageBox.Type.InGame, icon: Prefab.Icon)
|
||||||
{
|
{
|
||||||
IconColor = Prefab.IconColor
|
IconColor = Prefab.IconColor
|
||||||
};
|
};
|
||||||
|
yield return CoroutineStatus.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(IReadMessage msg)
|
public void ClientRead(IReadMessage msg)
|
||||||
|
|||||||
@@ -492,7 +492,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector2 MeasureString(string text)
|
public Vector2 MeasureString(string text, bool removeExtraSpacing = false)
|
||||||
{
|
{
|
||||||
if (text == null)
|
if (text == null)
|
||||||
{
|
{
|
||||||
@@ -501,7 +501,16 @@ namespace Barotrauma
|
|||||||
|
|
||||||
float currentLineX = 0.0f;
|
float currentLineX = 0.0f;
|
||||||
Vector2 retVal = Vector2.Zero;
|
Vector2 retVal = Vector2.Zero;
|
||||||
retVal.Y = baseHeight * 1.8f;
|
|
||||||
|
if (!removeExtraSpacing)
|
||||||
|
{
|
||||||
|
retVal.Y = baseHeight * 1.8f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retVal.Y = baseHeight;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < text.Length; i++)
|
for (int i = 0; i < text.Length; i++)
|
||||||
{
|
{
|
||||||
if (text[i] == '\n')
|
if (text[i] == '\n')
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
@@ -144,6 +145,15 @@ namespace Barotrauma
|
|||||||
GetSize(element);
|
GetSize(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Sprite GetDefaultSprite()
|
||||||
|
{
|
||||||
|
return GetSprite(GUIComponent.ComponentState.None);
|
||||||
|
}
|
||||||
|
public Sprite GetSprite(GUIComponent.ComponentState state)
|
||||||
|
{
|
||||||
|
return Sprites.ContainsKey(state) ? Sprites[state]?.First()?.Sprite : null;
|
||||||
|
}
|
||||||
|
|
||||||
public void GetSize(XElement element)
|
public void GetSize(XElement element)
|
||||||
{
|
{
|
||||||
Point size = new Point(0, 0);
|
Point size = new Point(0, 0);
|
||||||
|
|||||||
@@ -0,0 +1,729 @@
|
|||||||
|
using Barotrauma.Extensions;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using Barotrauma.Networking;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
class CrewManagement
|
||||||
|
{
|
||||||
|
private CampaignMode campaign => campaignUI.Campaign;
|
||||||
|
private readonly CampaignUI campaignUI;
|
||||||
|
private readonly GUIComponent parentComponent;
|
||||||
|
|
||||||
|
private GUIListBox hireableList, pendingList, crewList;
|
||||||
|
private GUIFrame characterPreviewFrame;
|
||||||
|
private GUIDropDown sortingDropDown;
|
||||||
|
private GUITextBlock totalBlock;
|
||||||
|
private GUIButton validateHiresButton;
|
||||||
|
private GUIButton clearAllButton;
|
||||||
|
|
||||||
|
private List<CharacterInfo> PendingHires => campaign.Map?.CurrentLocation?.HireManager?.PendingHires;
|
||||||
|
private bool HasPermission => campaignUI.Campaign.AllowedToManageCampaign();
|
||||||
|
|
||||||
|
private Point resolutionWhenCreated;
|
||||||
|
|
||||||
|
private enum SortingMethod
|
||||||
|
{
|
||||||
|
AlphabeticalAsc,
|
||||||
|
JobAsc,
|
||||||
|
PriceAsc,
|
||||||
|
PriceDesc,
|
||||||
|
SkillAsc,
|
||||||
|
SkillDesc
|
||||||
|
}
|
||||||
|
|
||||||
|
public CrewManagement(CampaignUI campaignUI, GUIComponent parentComponent)
|
||||||
|
{
|
||||||
|
this.campaignUI = campaignUI;
|
||||||
|
this.parentComponent = parentComponent;
|
||||||
|
|
||||||
|
CreateUI();
|
||||||
|
UpdateLocationView(campaignUI.Campaign.Map.CurrentLocation, true);
|
||||||
|
|
||||||
|
campaignUI.Campaign.Map.OnLocationChanged += (prevLocation, newLocation) => UpdateLocationView(newLocation, true, prevLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RefreshPermissions()
|
||||||
|
{
|
||||||
|
RefreshCrewFrames(hireableList);
|
||||||
|
RefreshCrewFrames(crewList);
|
||||||
|
RefreshCrewFrames(pendingList);
|
||||||
|
if (clearAllButton != null) { clearAllButton.Enabled = HasPermission; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshCrewFrames(GUIListBox listBox)
|
||||||
|
{
|
||||||
|
if (listBox == null) { return; }
|
||||||
|
listBox.CanBeFocused = HasPermission;
|
||||||
|
foreach (GUIComponent child in listBox.Content.Children)
|
||||||
|
{
|
||||||
|
if (child.FindChild(c => c is GUIButton && c.UserData is CharacterInfo, true) is GUIButton buyButton)
|
||||||
|
{
|
||||||
|
buyButton.Enabled = HasPermission;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateUI()
|
||||||
|
{
|
||||||
|
if (parentComponent.FindChild(c => c.UserData as string == "glow") is GUIComponent glowChild)
|
||||||
|
{
|
||||||
|
parentComponent.RemoveChild(glowChild);
|
||||||
|
}
|
||||||
|
if (parentComponent.FindChild(c => c.UserData as string == "container") is GUIComponent containerChild)
|
||||||
|
{
|
||||||
|
parentComponent.RemoveChild(containerChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
new GUIFrame(new RectTransform(new Vector2(1.25f, 1.25f), parentComponent.RectTransform, Anchor.Center),
|
||||||
|
style: "OuterGlow", color: Color.Black * 0.7f)
|
||||||
|
{
|
||||||
|
UserData = "glow"
|
||||||
|
};
|
||||||
|
new GUIFrame(new RectTransform(new Vector2(0.95f), parentComponent.RectTransform, anchor: Anchor.Center),
|
||||||
|
style: null)
|
||||||
|
{
|
||||||
|
CanBeFocused = false,
|
||||||
|
UserData = "container"
|
||||||
|
};
|
||||||
|
|
||||||
|
var availableMainGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 1.0f), campaignUI.GetTabContainer(CampaignMode.InteractionType.Crew).RectTransform)
|
||||||
|
{
|
||||||
|
MaxSize = new Point(560, campaignUI.GetTabContainer(CampaignMode.InteractionType.Crew).Rect.Height)
|
||||||
|
})
|
||||||
|
{
|
||||||
|
Stretch = true,
|
||||||
|
RelativeSpacing = 0.02f
|
||||||
|
};
|
||||||
|
|
||||||
|
// Header ------------------------------------------------
|
||||||
|
var headerGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.75f / 14.0f), availableMainGroup.RectTransform), isHorizontal: true)
|
||||||
|
{
|
||||||
|
RelativeSpacing = 0.005f
|
||||||
|
};
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
CanBeFocused = false,
|
||||||
|
ForceUpperCase = true
|
||||||
|
};
|
||||||
|
|
||||||
|
var hireablesGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.95f), anchor: Anchor.Center,
|
||||||
|
parent: new GUIFrame(new RectTransform(new Vector2(1.0f, 13.25f / 14.0f), availableMainGroup.RectTransform)).RectTransform))
|
||||||
|
{
|
||||||
|
RelativeSpacing = 0.015f,
|
||||||
|
Stretch = true
|
||||||
|
};
|
||||||
|
|
||||||
|
var sortGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.04f), hireablesGroup.RectTransform), isHorizontal: true)
|
||||||
|
{
|
||||||
|
RelativeSpacing = 0.015f
|
||||||
|
};
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), sortGroup.RectTransform), text: TextManager.Get("campaignstore.sortby"));
|
||||||
|
sortingDropDown = new GUIDropDown(new RectTransform(new Vector2(0.4f, 1.0f), sortGroup.RectTransform), elementCount: 5)
|
||||||
|
{
|
||||||
|
OnSelected = (child, userData) =>
|
||||||
|
{
|
||||||
|
SortCharacters(hireableList, (SortingMethod)userData);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var tag = "sortingmethod.";
|
||||||
|
sortingDropDown.AddItem(TextManager.Get(tag + SortingMethod.JobAsc), userData: SortingMethod.JobAsc);
|
||||||
|
sortingDropDown.AddItem(TextManager.Get(tag + SortingMethod.SkillAsc), userData: SortingMethod.SkillAsc);
|
||||||
|
sortingDropDown.AddItem(TextManager.Get(tag + SortingMethod.SkillDesc), userData: SortingMethod.SkillDesc);
|
||||||
|
sortingDropDown.AddItem(TextManager.Get(tag + SortingMethod.PriceAsc), userData: SortingMethod.PriceAsc);
|
||||||
|
sortingDropDown.AddItem(TextManager.Get(tag + SortingMethod.PriceDesc), userData: SortingMethod.PriceDesc);
|
||||||
|
|
||||||
|
hireableList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.96f),
|
||||||
|
hireablesGroup.RectTransform,
|
||||||
|
anchor: Anchor.Center))
|
||||||
|
{
|
||||||
|
Spacing = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
var pendingAndCrewMainGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 1.0f), campaignUI.GetTabContainer(CampaignMode.InteractionType.Crew).RectTransform, anchor: Anchor.TopRight)
|
||||||
|
{
|
||||||
|
MaxSize = new Point(560, campaignUI.GetTabContainer(CampaignMode.InteractionType.Crew).Rect.Height)
|
||||||
|
})
|
||||||
|
{
|
||||||
|
Stretch = true,
|
||||||
|
RelativeSpacing = 0.02f
|
||||||
|
};
|
||||||
|
|
||||||
|
var playerBalanceContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.75f / 14.0f), pendingAndCrewMainGroup.RectTransform), childAnchor: Anchor.TopRight)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
AutoScaleVertical = true,
|
||||||
|
ForceUpperCase = true
|
||||||
|
};
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), playerBalanceContainer.RectTransform),
|
||||||
|
"", font: GUI.SubHeadingFont, textAlignment: Alignment.TopRight)
|
||||||
|
{
|
||||||
|
AutoScaleVertical = true,
|
||||||
|
TextScale = 1.1f,
|
||||||
|
TextGetter = () => FormatCurrency(campaign.Money)
|
||||||
|
};
|
||||||
|
|
||||||
|
var pendingAndCrewGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.95f), anchor: Anchor.Center,
|
||||||
|
parent: new GUIFrame(new RectTransform(new Vector2(1.0f, 13.25f / 14.0f), pendingAndCrewMainGroup.RectTransform)
|
||||||
|
{
|
||||||
|
MaxSize = new Point(560, campaignUI.GetTabContainer(CampaignMode.InteractionType.Crew).Rect.Height)
|
||||||
|
}).RectTransform));
|
||||||
|
|
||||||
|
float height = 0.05f;
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, height), pendingAndCrewGroup.RectTransform), TextManager.Get("campaigncrew.pending"), font: GUI.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);
|
||||||
|
crewList = new GUIListBox(new RectTransform(new Vector2(1.0f, (8)* height), pendingAndCrewGroup.RectTransform))
|
||||||
|
{
|
||||||
|
Spacing = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
TextScale = 1.1f
|
||||||
|
};
|
||||||
|
group = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, height), pendingAndCrewGroup.RectTransform), isHorizontal: true, childAnchor: Anchor.TopRight)
|
||||||
|
{
|
||||||
|
RelativeSpacing = 0.01f
|
||||||
|
};
|
||||||
|
validateHiresButton = new GUIButton(new RectTransform(new Vector2(1.0f / 3.0f, 1.0f), group.RectTransform), text: TextManager.Get("campaigncrew.validate"))
|
||||||
|
{
|
||||||
|
ForceUpperCase = true,
|
||||||
|
OnClicked = (b, o) => ValidatePendingHires(true)
|
||||||
|
};
|
||||||
|
clearAllButton = new GUIButton(new RectTransform(new Vector2(1.0f / 3.0f, 1.0f), group.RectTransform), text: TextManager.Get("campaignstore.clearall"))
|
||||||
|
{
|
||||||
|
ForceUpperCase = true,
|
||||||
|
Enabled = HasPermission,
|
||||||
|
OnClicked = (b, o) => RemoveAllPendingHires()
|
||||||
|
};
|
||||||
|
|
||||||
|
resolutionWhenCreated = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateLocationView(Location location, bool removePending, Location prevLocation = null)
|
||||||
|
{
|
||||||
|
if (prevLocation != null && prevLocation == location && GameMain.NetworkMember != null) { return; }
|
||||||
|
|
||||||
|
if (characterPreviewFrame != null)
|
||||||
|
{
|
||||||
|
characterPreviewFrame.Parent?.RemoveChild(characterPreviewFrame);
|
||||||
|
characterPreviewFrame = null;
|
||||||
|
}
|
||||||
|
UpdateHireables(location);
|
||||||
|
if (pendingList != null)
|
||||||
|
{
|
||||||
|
if (removePending)
|
||||||
|
{
|
||||||
|
PendingHires?.Clear();
|
||||||
|
pendingList.Content.ClearChildren();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PendingHires?.ForEach(ci => AddPendingHire(ci));
|
||||||
|
}
|
||||||
|
SetTotalHireCost();
|
||||||
|
}
|
||||||
|
UpdateCrew();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateHireables(Location location)
|
||||||
|
{
|
||||||
|
if (hireableList != null)
|
||||||
|
{
|
||||||
|
hireableList.Content.Children.ToList().ForEach(c => hireableList.RemoveChild(c));
|
||||||
|
var hireableCharacters = location.GetHireableCharacters();
|
||||||
|
if (hireableCharacters.None())
|
||||||
|
{
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), hireableList.Content.RectTransform), TextManager.Get("HireUnavailable"), textAlignment: Alignment.Center)
|
||||||
|
{
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (CharacterInfo c in hireableCharacters)
|
||||||
|
{
|
||||||
|
if (c == null) { continue; }
|
||||||
|
CreateCharacterFrame(c, hireableList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sortingDropDown.SelectItem(SortingMethod.JobAsc);
|
||||||
|
hireableList.UpdateScrollBarSize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetHireables(Location location, List<CharacterInfo> availableHires)
|
||||||
|
{
|
||||||
|
HireManager hireManager = location.HireManager;
|
||||||
|
if (hireManager == null) { return; }
|
||||||
|
int hireVal = hireManager.AvailableCharacters.Aggregate(0, (curr, hire) => curr + hire.GetIdentifier());
|
||||||
|
int newVal = availableHires.Aggregate(0, (curr, hire) => curr + hire.GetIdentifier());
|
||||||
|
if (hireVal != newVal)
|
||||||
|
{
|
||||||
|
location.HireManager.AvailableCharacters = availableHires;
|
||||||
|
UpdateHireables(location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateCrew()
|
||||||
|
{
|
||||||
|
crewList.Content.Children.ToList().ForEach(c => crewList.Content.RemoveChild(c));
|
||||||
|
foreach (CharacterInfo c in GameMain.GameSession.CrewManager.GetCharacterInfos())
|
||||||
|
{
|
||||||
|
if (c == null || !((c.Character?.IsBot ?? true) || campaign is SinglePlayerCampaign)) { continue; }
|
||||||
|
CreateCharacterFrame(c, crewList);
|
||||||
|
}
|
||||||
|
SortCharacters(crewList, SortingMethod.JobAsc);
|
||||||
|
crewList.UpdateScrollBarSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SortCharacters(GUIListBox list, SortingMethod sortingMethod)
|
||||||
|
{
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
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));
|
||||||
|
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));
|
||||||
|
if (sortingMethod == SortingMethod.SkillDesc) { list.Content.RectTransform.ReverseChildren(); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateCharacterFrame(CharacterInfo characterInfo, GUIListBox listBox)
|
||||||
|
{
|
||||||
|
Skill skill = null;
|
||||||
|
Color? jobColor = null;
|
||||||
|
if (characterInfo.Job != null)
|
||||||
|
{
|
||||||
|
skill = characterInfo.Job?.PrimarySkill ?? characterInfo.Job.Skills.OrderByDescending(s => s.Level).FirstOrDefault();
|
||||||
|
jobColor = characterInfo.Job.Prefab.UIColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
GUIFrame frame = new GUIFrame(new RectTransform(new Point(listBox.Content.Rect.Width, 55), parent: listBox.Content.RectTransform), "ListBoxElement")
|
||||||
|
{
|
||||||
|
UserData = new Tuple<CharacterInfo, float>(characterInfo, skill != null ? 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)
|
||||||
|
{
|
||||||
|
Stretch = true
|
||||||
|
};
|
||||||
|
|
||||||
|
float portraitWidth = (0.8f * mainGroup.Rect.Height) / mainGroup.Rect.Width;
|
||||||
|
new GUICustomComponent(new RectTransform(new Vector2(portraitWidth, 0.8f), mainGroup.RectTransform),
|
||||||
|
onDraw: (sb, component) => characterInfo.DrawIcon(sb, component.Rect.Center.ToVector2(), targetAreaSize: component.Rect.Size.ToVector2()))
|
||||||
|
{
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
|
||||||
|
GUILayoutGroup nameAndJobGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.4f - portraitWidth, 0.8f), mainGroup.RectTransform));
|
||||||
|
GUITextBlock nameBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), nameAndJobGroup.RectTransform),
|
||||||
|
characterInfo.Name, textColor: jobColor, textAlignment: Alignment.BottomLeft)
|
||||||
|
{
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
jobBlock.Text = ToolBox.LimitString(jobBlock.Text, jobBlock.Font, jobBlock.Rect.Width);
|
||||||
|
|
||||||
|
float width = 0.6f / 3;
|
||||||
|
if (characterInfo.Job != null)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
if (jobColor.HasValue) { skillIcon.Color = jobColor.Value; }
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f - iconWidth, 1.0f), skillGroup.RectTransform), ((int)skill.Level).ToString(), textAlignment: Alignment.CenterLeft)
|
||||||
|
{
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listBox != crewList)
|
||||||
|
{
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(width, 1.0f), mainGroup.RectTransform), FormatCurrency(characterInfo.Salary), textAlignment: Alignment.Center)
|
||||||
|
{
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listBox == hireableList)
|
||||||
|
{
|
||||||
|
new GUIButton(new RectTransform(new Vector2(width, 0.9f), mainGroup.RectTransform), style: "CrewManagementAddButton")
|
||||||
|
{
|
||||||
|
UserData = characterInfo,
|
||||||
|
Enabled = HasPermission,
|
||||||
|
OnClicked = (b, o) => AddPendingHire(o as CharacterInfo)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (listBox == pendingList)
|
||||||
|
{
|
||||||
|
new GUIButton(new RectTransform(new Vector2(width, 0.9f), mainGroup.RectTransform), style: "CrewManagementRemoveButton")
|
||||||
|
{
|
||||||
|
UserData = characterInfo,
|
||||||
|
Enabled = HasPermission,
|
||||||
|
OnClicked = (b, o) => RemovePendingHire(o as CharacterInfo)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (listBox == crewList && campaign != null)
|
||||||
|
{
|
||||||
|
var currentCrew = GameMain.GameSession.CrewManager.GetCharacterInfos();
|
||||||
|
new GUIButton(new RectTransform(new Vector2(width, 0.9f), mainGroup.RectTransform), style: "CrewManagementFireButton")
|
||||||
|
{
|
||||||
|
UserData = characterInfo,
|
||||||
|
//can't fire if there's only one character in the crew
|
||||||
|
Enabled = currentCrew.Contains(characterInfo) && currentCrew.Count() > 1 && HasPermission,
|
||||||
|
OnClicked = (btn, obj) =>
|
||||||
|
{
|
||||||
|
var confirmDialog = new GUIMessageBox(
|
||||||
|
TextManager.Get("FireWarningHeader"),
|
||||||
|
TextManager.GetWithVariable("FireWarningText", "[charactername]", ((CharacterInfo)obj).Name),
|
||||||
|
new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||||
|
confirmDialog.Buttons[0].UserData = (CharacterInfo)obj;
|
||||||
|
confirmDialog.Buttons[0].OnClicked = FireCharacter;
|
||||||
|
confirmDialog.Buttons[0].OnClicked += confirmDialog.Close;
|
||||||
|
confirmDialog.Buttons[1].OnClicked = confirmDialog.Close;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateCharacterPreviewFrame(GUIListBox listBox, GUIFrame characterFrame, CharacterInfo characterInfo)
|
||||||
|
{
|
||||||
|
Pivot pivot = listBox == hireableList ? Pivot.TopLeft : Pivot.TopRight;
|
||||||
|
Point absoluteOffset = new Point(
|
||||||
|
pivot == Pivot.TopLeft ? listBox.Parent.Parent.Rect.Right + 5 : listBox.Parent.Parent.Rect.Left - 5,
|
||||||
|
characterFrame.Rect.Top);
|
||||||
|
int frameSize = (int)(GUI.Scale * 300);
|
||||||
|
if (GameMain.GraphicsHeight - (absoluteOffset.Y + frameSize) < 0)
|
||||||
|
{
|
||||||
|
pivot = listBox == hireableList ? Pivot.BottomLeft : Pivot.BottomRight;
|
||||||
|
absoluteOffset.Y = characterFrame.Rect.Bottom;
|
||||||
|
}
|
||||||
|
characterPreviewFrame = new GUIFrame(new RectTransform(new Point(frameSize), parent: campaignUI.GetTabContainer(CampaignMode.InteractionType.Crew).Parent.RectTransform, pivot: pivot)
|
||||||
|
{
|
||||||
|
AbsoluteOffset = absoluteOffset
|
||||||
|
}, style: "InnerFrame")
|
||||||
|
{
|
||||||
|
UserData = characterInfo
|
||||||
|
};
|
||||||
|
GUILayoutGroup mainGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.95f), characterPreviewFrame.RectTransform, anchor: Anchor.Center))
|
||||||
|
{
|
||||||
|
RelativeSpacing = 0.01f
|
||||||
|
};
|
||||||
|
|
||||||
|
// Character info
|
||||||
|
GUILayoutGroup infoGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.475f), mainGroup.RectTransform), isHorizontal: true);
|
||||||
|
GUILayoutGroup infoLabelGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 1.0f), infoGroup.RectTransform)) { Stretch = true };
|
||||||
|
GUILayoutGroup infoValueGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.6f, 1.0f), infoGroup.RectTransform)) { Stretch = true };
|
||||||
|
float blockHeight = 1.0f / 4;
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoLabelGroup.RectTransform), TextManager.Get("name"));
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoValueGroup.RectTransform), characterInfo.Name);
|
||||||
|
if (characterInfo.HasGenders)
|
||||||
|
{
|
||||||
|
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()));
|
||||||
|
}
|
||||||
|
if (characterInfo.Job is Job job)
|
||||||
|
{
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoLabelGroup.RectTransform), TextManager.Get("tabmenu.job"));
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoValueGroup.RectTransform), job.Name);
|
||||||
|
}
|
||||||
|
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(" ", "")));
|
||||||
|
}
|
||||||
|
infoLabelGroup.Recalculate();
|
||||||
|
infoValueGroup.Recalculate();
|
||||||
|
|
||||||
|
new GUIImage(new RectTransform(new Vector2(1.0f, 0.05f), mainGroup.RectTransform), "HorizontalLine");
|
||||||
|
|
||||||
|
// Skills
|
||||||
|
GUILayoutGroup skillGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.475f), mainGroup.RectTransform), isHorizontal: true);
|
||||||
|
GUILayoutGroup skillNameGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 1.0f), skillGroup.RectTransform));
|
||||||
|
GUILayoutGroup skillLevelGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.2f, 1.0f), skillGroup.RectTransform));
|
||||||
|
List<Skill> characterSkills = characterInfo.Job.Skills;
|
||||||
|
blockHeight = 1.0f / characterSkills.Count;
|
||||||
|
foreach (Skill skill in characterSkills)
|
||||||
|
{
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), skillNameGroup.RectTransform), TextManager.Get("SkillName." + skill.Identifier));
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), skillLevelGroup.RectTransform), ((int)skill.Level).ToString(), textAlignment: Alignment.Right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool SelectCharacter(GUIListBox listBox, GUIFrame characterFrame, CharacterInfo characterInfo)
|
||||||
|
{
|
||||||
|
if (characterPreviewFrame != null && characterPreviewFrame.UserData != characterInfo)
|
||||||
|
{
|
||||||
|
characterPreviewFrame.Parent?.RemoveChild(characterPreviewFrame);
|
||||||
|
characterPreviewFrame = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listBox == null || characterFrame == null || characterInfo == null) { return false; }
|
||||||
|
|
||||||
|
if (characterPreviewFrame == null)
|
||||||
|
{
|
||||||
|
CreateCharacterPreviewFrame(listBox, characterFrame, characterInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool AddPendingHire(CharacterInfo characterInfo, bool createNetworkMessage = true)
|
||||||
|
{
|
||||||
|
hireableList.Content.RemoveChild(hireableList.Content.FindChild(c => (c.UserData as Tuple<CharacterInfo, float>).Item1 == characterInfo));
|
||||||
|
hireableList.UpdateScrollBarSize();
|
||||||
|
if (!PendingHires.Contains(characterInfo)) { PendingHires.Add(characterInfo); }
|
||||||
|
CreateCharacterFrame(characterInfo, pendingList);
|
||||||
|
SortCharacters(pendingList, SortingMethod.JobAsc);
|
||||||
|
pendingList.UpdateScrollBarSize();
|
||||||
|
SetTotalHireCost();
|
||||||
|
if (createNetworkMessage) { SendCrewState(true); }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
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.UpdateScrollBarSize();
|
||||||
|
CreateCharacterFrame(characterInfo, hireableList);
|
||||||
|
SortCharacters(hireableList, (SortingMethod)sortingDropDown.SelectedItemData);
|
||||||
|
hireableList.UpdateScrollBarSize();
|
||||||
|
if (setTotalHireCost) { SetTotalHireCost(); }
|
||||||
|
if (createNetworkMessage) { SendCrewState(true); }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool RemoveAllPendingHires(bool createNetworkMessage = true)
|
||||||
|
{
|
||||||
|
pendingList.Content.Children.ToList().ForEach(c => RemovePendingHire((c.UserData as Tuple<CharacterInfo, float>).Item1, setTotalHireCost: false, createNetworkMessage));
|
||||||
|
SetTotalHireCost();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetTotalHireCost()
|
||||||
|
{
|
||||||
|
if (pendingList == null || totalBlock == null || validateHiresButton == null) { return; }
|
||||||
|
int total = 0;
|
||||||
|
pendingList.Content.Children.ForEach(c => total += (c.UserData as Tuple<CharacterInfo, float>).Item1.Salary);
|
||||||
|
totalBlock.Text = FormatCurrency(total);
|
||||||
|
bool enoughMoney = campaign != null ? total <= campaign.Money : true;
|
||||||
|
totalBlock.TextColor = enoughMoney ? Color.White : Color.Red;
|
||||||
|
validateHiresButton.Enabled = enoughMoney && pendingList.Content.RectTransform.Children.Any();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ValidatePendingHires(bool createNetworkEvent = false)
|
||||||
|
{
|
||||||
|
List<CharacterInfo> hires = new List<CharacterInfo>();
|
||||||
|
int total = 0;
|
||||||
|
foreach (GUIComponent c in pendingList.Content.Children.ToList())
|
||||||
|
{
|
||||||
|
if (c.UserData is Tuple<CharacterInfo, float> info)
|
||||||
|
{
|
||||||
|
hires.Add(info.Item1);
|
||||||
|
total += info.Item1.Salary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hires.None() || total > campaign.Money) { return false; }
|
||||||
|
|
||||||
|
bool atLeastOneHired = false;
|
||||||
|
foreach (CharacterInfo ci in hires)
|
||||||
|
{
|
||||||
|
if (campaign.TryHireCharacter(campaign.Map.CurrentLocation, ci))
|
||||||
|
{
|
||||||
|
atLeastOneHired = true;
|
||||||
|
PendingHires.Remove(ci);
|
||||||
|
pendingList.Content.RemoveChild(pendingList.Content.FindChild(c => (c.UserData as Tuple<CharacterInfo, float>).Item1 == ci));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (atLeastOneHired)
|
||||||
|
{
|
||||||
|
UpdateLocationView(campaign.Map.CurrentLocation, true);
|
||||||
|
SelectCharacter(null, null, null);
|
||||||
|
var dialog = new GUIMessageBox(
|
||||||
|
TextManager.Get("newcrewmembers"),
|
||||||
|
TextManager.GetWithVariable("crewhiredmessage", "[location]", campaignUI?.Campaign?.Map?.CurrentLocation?.Name),
|
||||||
|
new string[] { TextManager.Get("Ok") });
|
||||||
|
dialog.Buttons[0].OnClicked += dialog.Close;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (createNetworkEvent)
|
||||||
|
{
|
||||||
|
SendCrewState(true, validateHires: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool FireCharacter(GUIButton button, object selection)
|
||||||
|
{
|
||||||
|
if (!(selection is CharacterInfo characterInfo)) { return false; }
|
||||||
|
|
||||||
|
campaign.CrewManager.FireCharacter(characterInfo);
|
||||||
|
SelectCharacter(null, null, null);
|
||||||
|
UpdateCrew();
|
||||||
|
|
||||||
|
SendCrewState(false, firedCharacter: characterInfo);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
if (GameMain.GraphicsWidth != resolutionWhenCreated.X || GameMain.GraphicsHeight != resolutionWhenCreated.Y)
|
||||||
|
{
|
||||||
|
CreateUI();
|
||||||
|
UpdateLocationView(campaign.Map.CurrentLocation, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((GUI.MouseOn?.UserData as Tuple<CharacterInfo, float>)?.Item1 is CharacterInfo characterInfo)
|
||||||
|
{
|
||||||
|
if (characterPreviewFrame == null || characterInfo != characterPreviewFrame.UserData)
|
||||||
|
{
|
||||||
|
GUIComponent component = GUI.MouseOn;
|
||||||
|
GUIListBox listBox = null;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (component.Parent is GUIListBox)
|
||||||
|
{
|
||||||
|
listBox = component.Parent as GUIListBox;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (component.Parent != null)
|
||||||
|
{
|
||||||
|
component = component.Parent;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (listBox == null);
|
||||||
|
|
||||||
|
if (listBox != null)
|
||||||
|
{
|
||||||
|
SelectCharacter(listBox, GUI.MouseOn as GUIFrame, characterInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: Reposition the current preview panel if necessary
|
||||||
|
// Could happen if we scroll a list while hovering?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (characterPreviewFrame != null)
|
||||||
|
{
|
||||||
|
characterPreviewFrame.Parent?.RemoveChild(characterPreviewFrame);
|
||||||
|
characterPreviewFrame = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetPendingHires(List<int> characterInfos, Location location)
|
||||||
|
{
|
||||||
|
List<CharacterInfo> oldHires = PendingHires.ToList();
|
||||||
|
foreach (CharacterInfo pendingHire in oldHires)
|
||||||
|
{
|
||||||
|
RemovePendingHire(pendingHire, createNetworkMessage: false);
|
||||||
|
}
|
||||||
|
PendingHires.Clear();
|
||||||
|
foreach (int identifier in characterInfos)
|
||||||
|
{
|
||||||
|
CharacterInfo match = location.HireManager.AvailableCharacters.Find(info => info.GetIdentifier() == identifier);
|
||||||
|
if (match != null)
|
||||||
|
{
|
||||||
|
PendingHires.Add(match);
|
||||||
|
AddPendingHire(match, createNetworkMessage: false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("Received a hire that doesn't exist.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Notify the server of crew changes
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="updatePending">When set to true will tell the server to update the pending hires</param>
|
||||||
|
/// <param name="firedCharacter">When not null tell the server to fire this character</param>
|
||||||
|
/// <param name="validateHires">When set to true will tell the server to validate pending hires</param>
|
||||||
|
public void SendCrewState(bool updatePending, CharacterInfo firedCharacter = null, bool validateHires = false)
|
||||||
|
{
|
||||||
|
if (campaign is MultiPlayerCampaign)
|
||||||
|
{
|
||||||
|
IWriteMessage msg = new WriteOnlyMessage();
|
||||||
|
msg.Write((byte)ClientPacketHeader.CREW);
|
||||||
|
|
||||||
|
msg.Write(updatePending);
|
||||||
|
if (updatePending)
|
||||||
|
{
|
||||||
|
msg.Write((ushort)PendingHires.Count);
|
||||||
|
foreach (CharacterInfo pendingHire in PendingHires)
|
||||||
|
{
|
||||||
|
msg.Write(pendingHire.GetIdentifier());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.Write(validateHires);
|
||||||
|
|
||||||
|
msg.Write(firedCharacter != null);
|
||||||
|
if (firedCharacter != null)
|
||||||
|
{
|
||||||
|
msg.Write(firedCharacter.GetIdentifier());
|
||||||
|
}
|
||||||
|
|
||||||
|
GameMain.Client.ClientPeer?.Send(msg, DeliveryMethod.Reliable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string FormatCurrency(int currency) => TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", currency));
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using System;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
@@ -146,6 +147,11 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool Pulse { get; set; }
|
||||||
|
private float pulseTimer;
|
||||||
|
private float pulseExpand;
|
||||||
|
private bool flashed;
|
||||||
|
|
||||||
public GUIButton(RectTransform rectT, string text = "", Alignment textAlignment = Alignment.Center, string style = "", Color? color = null) : base(style, rectT)
|
public GUIButton(RectTransform rectT, string text = "", Alignment textAlignment = Alignment.Center, string style = "", Color? color = null) : base(style, rectT)
|
||||||
{
|
{
|
||||||
CanBeFocused = true;
|
CanBeFocused = true;
|
||||||
@@ -196,7 +202,14 @@ namespace Barotrauma
|
|||||||
|
|
||||||
protected override void Draw(SpriteBatch spriteBatch)
|
protected override void Draw(SpriteBatch spriteBatch)
|
||||||
{
|
{
|
||||||
//do nothing
|
if (Pulse && pulseTimer > 1.0f)
|
||||||
|
{
|
||||||
|
Rectangle expandRect = Rect;
|
||||||
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Update(float deltaTime)
|
protected override void Update(float deltaTime)
|
||||||
@@ -244,13 +257,41 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
State = Selected ? ComponentState.Selected : ComponentState.None;
|
if (!ExternalHighlight)
|
||||||
|
{
|
||||||
|
State = Selected ? ComponentState.Selected : ComponentState.None;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
State = ComponentState.Hover;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (GUIComponent child in Children)
|
foreach (GUIComponent child in Children)
|
||||||
{
|
{
|
||||||
child.State = State;
|
child.State = State;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Pulse)
|
||||||
|
{
|
||||||
|
pulseTimer += deltaTime;
|
||||||
|
if (pulseTimer > 1.0f)
|
||||||
|
{
|
||||||
|
if (!flashed)
|
||||||
|
{
|
||||||
|
flashed = true;
|
||||||
|
Frame.Flash(Color.White * 0.2f, 0.8f, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
pulseExpand += deltaTime;
|
||||||
|
if (pulseExpand > 1.0f)
|
||||||
|
{
|
||||||
|
pulseTimer = 0.0f;
|
||||||
|
pulseExpand = 0.0f;
|
||||||
|
flashed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace Barotrauma
|
|||||||
_instance = new GUICanvas();
|
_instance = new GUICanvas();
|
||||||
if (GameMain.Instance != null)
|
if (GameMain.Instance != null)
|
||||||
{
|
{
|
||||||
GameMain.Instance.OnResolutionChanged += RecalculateSize;
|
GameMain.Instance.ResolutionChanged += RecalculateSize;
|
||||||
}
|
}
|
||||||
_instance.ItemComponentHolder = new GUIFrame(new RectTransform(Vector2.One, _instance, Anchor.Center)).RectTransform;
|
_instance.ItemComponentHolder = new GUIFrame(new RectTransform(Vector2.One, _instance, Anchor.Center)).RectTransform;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
using Microsoft.Xna.Framework;
|
|
||||||
|
|
||||||
namespace Barotrauma
|
|
||||||
{
|
|
||||||
public class GUIColorSettings
|
|
||||||
{
|
|
||||||
// Inventory
|
|
||||||
public static Color EquipmentSlotIconColor = new Color(99, 70, 64);
|
|
||||||
|
|
||||||
// Health HUD
|
|
||||||
public static Color BuffColorLow = Color.LightGreen;
|
|
||||||
public static Color BuffColorMedium = Color.Green;
|
|
||||||
public static Color BuffColorHigh = Color.DarkGreen;
|
|
||||||
|
|
||||||
public static Color DebuffColorLow = Color.DarkSalmon;
|
|
||||||
public static Color DebuffColorMedium = Color.Red;
|
|
||||||
public static Color DebuffColorHigh = Color.DarkRed;
|
|
||||||
|
|
||||||
public static Color HealthBarColorLow = Color.Red;
|
|
||||||
public static Color HealthBarColorMedium = Color.Orange;
|
|
||||||
public static Color HealthBarColorHigh = new Color(78, 114, 88);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -11,6 +11,8 @@ using System.Net;
|
|||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
|
public enum SlideDirection { Up, Down, Left, Right }
|
||||||
|
|
||||||
public abstract class GUIComponent
|
public abstract class GUIComponent
|
||||||
{
|
{
|
||||||
#region Hierarchy
|
#region Hierarchy
|
||||||
@@ -18,6 +20,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public CursorState HoverCursor = CursorState.Default;
|
public CursorState HoverCursor = CursorState.Default;
|
||||||
|
|
||||||
|
public bool AlwaysOverrideCursor = false;
|
||||||
|
|
||||||
public delegate bool SecondaryButtonDownHandler(GUIComponent component, object userData);
|
public delegate bool SecondaryButtonDownHandler(GUIComponent component, object userData);
|
||||||
public SecondaryButtonDownHandler OnSecondaryClicked;
|
public SecondaryButtonDownHandler OnSecondaryClicked;
|
||||||
|
|
||||||
@@ -75,7 +79,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public virtual void RemoveChild(GUIComponent child)
|
public virtual void RemoveChild(GUIComponent child)
|
||||||
{
|
{
|
||||||
if (child == null) return;
|
if (child == null) { return; }
|
||||||
child.RectTransform.Parent = null;
|
child.RectTransform.Parent = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,6 +144,11 @@ namespace Barotrauma
|
|||||||
public bool AutoDraw { get; set; } = true;
|
public bool AutoDraw { get; set; } = true;
|
||||||
public int UpdateOrder { get; set; }
|
public int UpdateOrder { get; set; }
|
||||||
|
|
||||||
|
public bool Bounce { get; set; }
|
||||||
|
private float bounceTimer;
|
||||||
|
private float bounceJump;
|
||||||
|
private bool bounceDown;
|
||||||
|
|
||||||
public Action<GUIComponent> OnAddedToGUIUpdateList;
|
public Action<GUIComponent> OnAddedToGUIUpdateList;
|
||||||
|
|
||||||
public enum ComponentState { None, Hover, Pressed, Selected, HoverSelected };
|
public enum ComponentState { None, Hover, Pressed, Selected, HoverSelected };
|
||||||
@@ -158,6 +167,8 @@ namespace Barotrauma
|
|||||||
protected Color disabledColor;
|
protected Color disabledColor;
|
||||||
protected Color pressedColor;
|
protected Color pressedColor;
|
||||||
|
|
||||||
|
public bool GlowOnSelect { get; set; }
|
||||||
|
|
||||||
private CoroutineHandle pulsateCoroutine;
|
private CoroutineHandle pulsateCoroutine;
|
||||||
|
|
||||||
protected Color flashColor;
|
protected Color flashColor;
|
||||||
@@ -327,6 +338,11 @@ namespace Barotrauma
|
|||||||
get { return RectTransform.CountChildren; }
|
get { return RectTransform.CountChildren; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Currently only used for the fade effect in GUIListBox, should be set to the same value as Color but only assigned once
|
||||||
|
/// </summary>
|
||||||
|
public Color DefaultColor { get; set; }
|
||||||
|
|
||||||
public virtual Color Color
|
public virtual Color Color
|
||||||
{
|
{
|
||||||
get { return color; }
|
get { return color; }
|
||||||
@@ -463,6 +479,36 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Bounce)
|
||||||
|
{
|
||||||
|
if (bounceTimer > 3.0f || bounceDown)
|
||||||
|
{
|
||||||
|
RectTransform.ScreenSpaceOffset = new Point(RectTransform.ScreenSpaceOffset.X, (int) -(bounceJump * 10f));
|
||||||
|
if (!bounceDown)
|
||||||
|
{
|
||||||
|
bounceJump += deltaTime * 4;
|
||||||
|
if (bounceJump > 0.5f)
|
||||||
|
{
|
||||||
|
bounceDown = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bounceJump -= deltaTime * 4;
|
||||||
|
if (bounceJump <= 0.0f)
|
||||||
|
{
|
||||||
|
bounceJump = 0.0f;
|
||||||
|
bounceTimer = 0.0f;
|
||||||
|
bounceDown = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bounceTimer += deltaTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (flashTimer > 0.0f)
|
if (flashTimer > 0.0f)
|
||||||
{
|
{
|
||||||
flashTimer -= deltaTime;
|
flashTimer -= deltaTime;
|
||||||
@@ -526,12 +572,14 @@ namespace Barotrauma
|
|||||||
protected virtual Color GetColor(ComponentState state)
|
protected virtual Color GetColor(ComponentState state)
|
||||||
{
|
{
|
||||||
if (!Enabled) { return DisabledColor; }
|
if (!Enabled) { return DisabledColor; }
|
||||||
|
if (ExternalHighlight) { return HoverColor; }
|
||||||
|
|
||||||
return state switch
|
return state switch
|
||||||
{
|
{
|
||||||
ComponentState.Hover => HoverColor,
|
ComponentState.Hover => HoverColor,
|
||||||
ComponentState.HoverSelected => HoverColor,
|
ComponentState.HoverSelected => HoverColor,
|
||||||
ComponentState.Pressed => PressedColor,
|
ComponentState.Pressed => PressedColor,
|
||||||
ComponentState.Selected => SelectedColor,
|
ComponentState.Selected when !GlowOnSelect => SelectedColor,
|
||||||
_ => Color,
|
_ => Color,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -619,6 +667,11 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GlowOnSelect && State == ComponentState.Selected)
|
||||||
|
{
|
||||||
|
GUI.UIGlow.Draw(spriteBatch, Rect, SelectedColor);
|
||||||
|
}
|
||||||
|
|
||||||
if (flashTimer > 0.0f)
|
if (flashTimer > 0.0f)
|
||||||
{
|
{
|
||||||
//the number of flashes depends on the duration, 1 flash per 1 full second
|
//the number of flashes depends on the duration, 1 flash per 1 full second
|
||||||
@@ -690,6 +743,7 @@ namespace Barotrauma
|
|||||||
protected virtual void SetAlpha(float a)
|
protected virtual void SetAlpha(float a)
|
||||||
{
|
{
|
||||||
color = new Color(color.R / 255.0f, color.G / 255.0f, color.B / 255.0f, a);
|
color = new Color(color.R / 255.0f, color.G / 255.0f, color.B / 255.0f, a);
|
||||||
|
hoverColor = new Color(hoverColor.R / 255.0f, hoverColor.G / 255.0f, hoverColor.B / 255.0f, a);;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Flash(Color? color = null, float flashDuration = 1.5f, bool useRectangleFlash = false, bool useCircularFlash = false, Vector2? flashRectInflate = null)
|
public virtual void Flash(Color? color = null, float flashDuration = 1.5f, bool useRectangleFlash = false, bool useCircularFlash = false, Vector2? flashRectInflate = null)
|
||||||
@@ -707,10 +761,77 @@ namespace Barotrauma
|
|||||||
CoroutineManager.StartCoroutine(LerpAlpha(0.0f, duration, removeAfter));
|
CoroutineManager.StartCoroutine(LerpAlpha(0.0f, duration, removeAfter));
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<object> LerpAlpha(float to, float duration, bool removeAfter)
|
public void FadeIn(float wait, float duration)
|
||||||
|
{
|
||||||
|
SetAlpha(0.0f);
|
||||||
|
CoroutineManager.StartCoroutine(LerpAlpha(1.0f, duration, false, wait));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SlideIn(float wait, float duration, int amount, SlideDirection direction)
|
||||||
|
{
|
||||||
|
RectTransform.ScreenSpaceOffset = direction switch
|
||||||
|
{
|
||||||
|
SlideDirection.Up => new Point(0, amount),
|
||||||
|
SlideDirection.Down => new Point(0, -amount),
|
||||||
|
SlideDirection.Left => new Point(amount, 0),
|
||||||
|
SlideDirection.Right => new Point(-amount, 0),
|
||||||
|
_ => RectTransform.ScreenSpaceOffset
|
||||||
|
};
|
||||||
|
CoroutineManager.StartCoroutine(SlideToPosition(duration, wait, Vector2.Zero));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SlideOut(float duration, int amount, SlideDirection direction)
|
||||||
|
{
|
||||||
|
RectTransform.ScreenSpaceOffset = Point.Zero;
|
||||||
|
|
||||||
|
Vector2 targetPos = direction switch
|
||||||
|
{
|
||||||
|
SlideDirection.Up => new Vector2(0, amount),
|
||||||
|
SlideDirection.Down => new Vector2(0, -amount),
|
||||||
|
SlideDirection.Left => new Vector2(amount, 0),
|
||||||
|
SlideDirection.Right => new Vector2(-amount, 0),
|
||||||
|
_ => Vector2.Zero
|
||||||
|
};
|
||||||
|
|
||||||
|
CoroutineManager.StartCoroutine(SlideToPosition(duration, 0.0f, targetPos));
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<object> SlideToPosition(float duration, float wait, Vector2 target)
|
||||||
{
|
{
|
||||||
float t = 0.0f;
|
float t = 0.0f;
|
||||||
float startA = color.A;
|
var (startX, startY) = RectTransform.ScreenSpaceOffset.ToVector2();
|
||||||
|
var (endX, endY) = target;
|
||||||
|
while (t < wait)
|
||||||
|
{
|
||||||
|
t += CoroutineManager.DeltaTime;
|
||||||
|
yield return CoroutineStatus.Running;
|
||||||
|
}
|
||||||
|
t = 0.0f;
|
||||||
|
|
||||||
|
while (t < duration)
|
||||||
|
{
|
||||||
|
t += CoroutineManager.DeltaTime;
|
||||||
|
RectTransform.ScreenSpaceOffset = new Point((int)MathHelper.Lerp(startX, endX, t / duration), (int)MathHelper.Lerp(startY, endY, t / duration));
|
||||||
|
yield return CoroutineStatus.Running;
|
||||||
|
}
|
||||||
|
|
||||||
|
RectTransform.ScreenSpaceOffset = new Point(0, 0);
|
||||||
|
|
||||||
|
yield return CoroutineStatus.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<object> LerpAlpha(float to, float duration, bool removeAfter, float wait = 0.0f)
|
||||||
|
{
|
||||||
|
State = ComponentState.None;
|
||||||
|
float t = 0.0f;
|
||||||
|
float startA = color.A / 255.0f;
|
||||||
|
|
||||||
|
while (t < wait)
|
||||||
|
{
|
||||||
|
t += CoroutineManager.DeltaTime;
|
||||||
|
yield return CoroutineStatus.Running;
|
||||||
|
}
|
||||||
|
t = 0.0f;
|
||||||
|
|
||||||
while (t < duration)
|
while (t < duration)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
public class GUIFrame : GUIComponent
|
public class GUIFrame : GUIComponent
|
||||||
{
|
{
|
||||||
|
public int OutlineThickness { get; set; }
|
||||||
|
|
||||||
public GUIFrame(RectTransform rectT, string style = "", Color? color = null) : base(style, rectT)
|
public GUIFrame(RectTransform rectT, string style = "", Color? color = null) : base(style, rectT)
|
||||||
{
|
{
|
||||||
Enabled = true;
|
Enabled = true;
|
||||||
@@ -26,7 +28,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (OutlineColor != Color.Transparent)
|
if (OutlineColor != Color.Transparent)
|
||||||
{
|
{
|
||||||
GUI.DrawRectangle(spriteBatch, Rect, OutlineColor * (OutlineColor.A/255.0f), false);
|
GUI.DrawRectangle(spriteBatch, Rect, OutlineColor * (OutlineColor.A/255.0f), false, thickness: OutlineThickness);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,17 +42,32 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
return crop;
|
return crop;
|
||||||
}
|
}
|
||||||
set
|
}
|
||||||
|
|
||||||
|
public void SetCrop(bool state, bool center = true)
|
||||||
|
{
|
||||||
|
crop = state;
|
||||||
|
if (crop && sprite != null)
|
||||||
{
|
{
|
||||||
crop = value;
|
sourceRect.Width = Math.Min(sprite.SourceRect.Width, (int)(Rect.Width / Scale));
|
||||||
if (crop)
|
sourceRect.Height = Math.Min(sprite.SourceRect.Height, (int)(Rect.Height / Scale));
|
||||||
|
|
||||||
|
if (center)
|
||||||
{
|
{
|
||||||
sourceRect.Width = Math.Min(sprite.SourceRect.Width, Rect.Width);
|
sourceRect.X = (sprite.SourceRect.Width - sourceRect.Width) / 2;
|
||||||
sourceRect.Height = Math.Min(sprite.SourceRect.Height, Rect.Height);
|
sourceRect.Y = (sprite.SourceRect.Height - sourceRect.Height) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
origin = sourceRect.Size.ToVector2() / 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
origin = sprite == null ? Vector2.Zero : sprite.size / 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Vector2 origin;
|
||||||
|
|
||||||
public float Scale
|
public float Scale
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
@@ -72,7 +87,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (sprite == value) return;
|
if (sprite == value) return;
|
||||||
sprite = value;
|
sprite = value;
|
||||||
sourceRect = sprite.SourceRect;
|
sourceRect = value == null ? Rectangle.Empty : value.SourceRect;
|
||||||
|
origin = value == null ? Vector2.Zero : value.size / 2;
|
||||||
if (scaleToFit) RecalculateScale();
|
if (scaleToFit) RecalculateScale();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,7 +150,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
loadingTextures = true;
|
loadingTextures = true;
|
||||||
loading = true;
|
loading = true;
|
||||||
TaskPool.Add(LoadTextureAsync(), (Task) =>
|
TaskPool.Add("LoadTextureAsync",
|
||||||
|
LoadTextureAsync(), (Task) =>
|
||||||
{
|
{
|
||||||
loading = false;
|
loading = false;
|
||||||
lazyLoaded = true;
|
lazyLoaded = true;
|
||||||
@@ -178,7 +195,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else if (sprite?.Texture != null)
|
else if (sprite?.Texture != null)
|
||||||
{
|
{
|
||||||
spriteBatch.Draw(sprite.Texture, Rect.Center.ToVector2(), sourceRect, currentColor * (currentColor.A / 255.0f), Rotation, sprite.size / 2,
|
spriteBatch.Draw(sprite.Texture, Rect.Center.ToVector2(), sourceRect, currentColor * (currentColor.A / 255.0f), Rotation, origin,
|
||||||
Scale, SpriteEffects, 0.0f);
|
Scale, SpriteEffects, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ namespace Barotrauma
|
|||||||
(RectTransform.Children.Count(c => !c.GUIComponent.IgnoreLayoutGroups) - 1) *
|
(RectTransform.Children.Count(c => !c.GUIComponent.IgnoreLayoutGroups) - 1) *
|
||||||
(absoluteSpacing + relativeSpacing * thisSize);
|
(absoluteSpacing + relativeSpacing * thisSize);
|
||||||
|
|
||||||
stretchFactor = totalSize <= 0.0f || minSize >= thisSize ?
|
stretchFactor = totalSize <= 0.0f || minSize >= thisSize || totalSize == minSize ?
|
||||||
1.0f :
|
1.0f :
|
||||||
(thisSize - minSize) / (totalSize - minSize);
|
(thisSize - minSize) / (totalSize - minSize);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,37 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private bool useGridLayout;
|
private bool useGridLayout;
|
||||||
|
|
||||||
|
private float targetScroll;
|
||||||
|
|
||||||
|
private GUIComponent pendingScroll;
|
||||||
|
|
||||||
|
public bool AllowMouseWheelScroll { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Scrolls the list smoothly
|
||||||
|
/// </summary>
|
||||||
|
public bool SmoothScroll { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether to only allow scrolling from one element to the next when smooth scrolling is enabled
|
||||||
|
/// </summary>
|
||||||
|
public bool ClampScrollToElements { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When set to true elements at the bottom of the list are gradually faded
|
||||||
|
/// </summary>
|
||||||
|
public bool FadeElements { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds enough extra padding to the bottom so the end of the scroll will only contain the last element
|
||||||
|
/// </summary>
|
||||||
|
public bool PadBottom { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When set to true always selects the topmost item on the list
|
||||||
|
/// </summary>
|
||||||
|
public bool SelectTop { get; set; }
|
||||||
|
|
||||||
public bool UseGridLayout
|
public bool UseGridLayout
|
||||||
{
|
{
|
||||||
get { return useGridLayout; }
|
get { return useGridLayout; }
|
||||||
@@ -190,9 +221,12 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public GUIComponent DraggedElement => draggedElement;
|
public GUIComponent DraggedElement => draggedElement;
|
||||||
|
|
||||||
|
private bool scheduledScroll = false;
|
||||||
|
|
||||||
/// <param name="isScrollBarOnDefaultSide">For horizontal listbox, default side is on the bottom. For vertical, it's on the right.</param>
|
/// <param name="isScrollBarOnDefaultSide">For horizontal listbox, default side is on the bottom. For vertical, it's on the right.</param>
|
||||||
public GUIListBox(RectTransform rectT, bool isHorizontal = false, Color? color = null, string style = "", bool isScrollBarOnDefaultSide = true, bool useMouseDownToSelect = false) : base(style, rectT)
|
public GUIListBox(RectTransform rectT, bool isHorizontal = false, Color? color = null, string style = "", bool isScrollBarOnDefaultSide = true, bool useMouseDownToSelect = false) : base(style, rectT)
|
||||||
{
|
{
|
||||||
|
HoverCursor = CursorState.Hand;
|
||||||
CanBeFocused = true;
|
CanBeFocused = true;
|
||||||
selected = new List<GUIComponent>();
|
selected = new List<GUIComponent>();
|
||||||
this.useMouseDownToSelect = useMouseDownToSelect;
|
this.useMouseDownToSelect = useMouseDownToSelect;
|
||||||
@@ -364,6 +398,49 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Scrolls the list to the specific element, currently only works when smooth scrolling and PadBottom are enabled.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="component"></param>
|
||||||
|
public void ScrollToElement(GUIComponent component)
|
||||||
|
{
|
||||||
|
GUI.PlayUISound(GUISoundType.Click);
|
||||||
|
List<GUIComponent> children = Content.Children.ToList();
|
||||||
|
int index = children.IndexOf(component);
|
||||||
|
if (index < 0) { return; }
|
||||||
|
|
||||||
|
targetScroll = MathHelper.Clamp(MathHelper.Lerp(0, 1, MathUtils.InverseLerp(0, (children.Count - 0.9f), index)), ScrollBar.MinValue, ScrollBar.MaxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ScrollToEnd(float duration)
|
||||||
|
{
|
||||||
|
CoroutineManager.StartCoroutine(ScrollCoroutine());
|
||||||
|
|
||||||
|
IEnumerable<object> ScrollCoroutine()
|
||||||
|
{
|
||||||
|
if (BarSize >= 1.0f)
|
||||||
|
{
|
||||||
|
yield return CoroutineStatus.Success;
|
||||||
|
}
|
||||||
|
float t = 0.0f;
|
||||||
|
float startScroll = BarScroll * BarSize;
|
||||||
|
float distanceToTravel = ScrollBar.MaxValue - startScroll;
|
||||||
|
float progress = startScroll;
|
||||||
|
float speed = distanceToTravel / duration;
|
||||||
|
|
||||||
|
while (t < duration && !MathUtils.NearlyEqual(ScrollBar.MaxValue, progress))
|
||||||
|
{
|
||||||
|
t += CoroutineManager.DeltaTime;
|
||||||
|
progress += speed * CoroutineManager.DeltaTime;
|
||||||
|
BarScroll = progress;
|
||||||
|
yield return CoroutineStatus.Running;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return CoroutineStatus.Success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void UpdateChildrenRect()
|
private void UpdateChildrenRect()
|
||||||
{
|
{
|
||||||
//dragging
|
//dragging
|
||||||
@@ -404,6 +481,32 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SelectTop)
|
||||||
|
{
|
||||||
|
foreach (GUIComponent child in Content.Children)
|
||||||
|
{
|
||||||
|
child.CanBeFocused = !selected.Contains(child);
|
||||||
|
if (!child.CanBeFocused)
|
||||||
|
{
|
||||||
|
child.State = ComponentState.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SelectTop && Content.Children.Any() && pendingScroll == null)
|
||||||
|
{
|
||||||
|
GUIComponent component = Content.Children.FirstOrDefault(c => (c.Rect.Y - Content.Rect.Y) / (float)c.Rect.Height > -0.1f);
|
||||||
|
|
||||||
|
if (component != null && !selected.Contains(component))
|
||||||
|
{
|
||||||
|
int index = Content.Children.ToList().IndexOf(component);
|
||||||
|
if (index >= 0)
|
||||||
|
{
|
||||||
|
Select(index, false, false, takeKeyBoardFocus: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < Content.CountChildren; i++)
|
for (int i = 0; i < Content.CountChildren; i++)
|
||||||
{
|
{
|
||||||
var child = Content.RectTransform.GetChild(i)?.GUIComponent;
|
var child = Content.RectTransform.GetChild(i)?.GUIComponent;
|
||||||
@@ -418,7 +521,16 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (mouseDown)
|
if (mouseDown)
|
||||||
{
|
{
|
||||||
Select(i, autoScroll: false);
|
if (SelectTop)
|
||||||
|
{
|
||||||
|
pendingScroll = child;
|
||||||
|
ScrollToElement(child);
|
||||||
|
Select(i, autoScroll: false, takeKeyBoardFocus: true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Select(i, autoScroll: false, takeKeyBoardFocus: true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CanDragElements && PlayerInput.LeftButtonDown() && GUI.MouseOn == child)
|
if (CanDragElements && PlayerInput.LeftButtonDown() && GUI.MouseOn == child)
|
||||||
@@ -538,10 +650,93 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
UpdateScrollBarSize();
|
UpdateScrollBarSize();
|
||||||
}
|
}
|
||||||
if ((GUI.IsMouseOn(this) || GUI.IsMouseOn(ScrollBar)) && PlayerInput.ScrollWheelSpeed != 0)
|
|
||||||
|
|
||||||
|
if (FadeElements)
|
||||||
{
|
{
|
||||||
ScrollBar.BarScroll -= (PlayerInput.ScrollWheelSpeed / 500.0f) * BarSize;
|
foreach (var (component, _) in childVisible)
|
||||||
|
{
|
||||||
|
float lerp = 0;
|
||||||
|
float y = component.Rect.Y;
|
||||||
|
float contentY = Content.Rect.Y;
|
||||||
|
float height = component.Rect.Height;
|
||||||
|
if (y < Content.Rect.Y)
|
||||||
|
{
|
||||||
|
float distance = (contentY - y) / height;
|
||||||
|
lerp = distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
float centerY = Content.Rect.Y + Content.Rect.Height / 2.0f;
|
||||||
|
if (y > centerY)
|
||||||
|
{
|
||||||
|
float distance = (y - centerY) / (centerY - height);
|
||||||
|
lerp = distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
component.Color = component.HoverColor = ToolBox.GradientLerp(lerp, component.DefaultColor, Color.Transparent);
|
||||||
|
component.DisabledColor = ToolBox.GradientLerp(lerp, component.Style.DisabledColor, Color.Transparent);
|
||||||
|
component.HoverColor = ToolBox.GradientLerp(lerp, component.Style.HoverColor, Color.Transparent);
|
||||||
|
|
||||||
|
foreach (var child in component.GetAllChildren())
|
||||||
|
{
|
||||||
|
Color gradient = ToolBox.GradientLerp(lerp, child.DefaultColor, Color.Transparent);
|
||||||
|
child.Color = child.HoverColor = gradient;
|
||||||
|
if (child is GUITextBlock block)
|
||||||
|
{
|
||||||
|
block.TextColor = block.HoverTextColor = gradient;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SmoothScroll)
|
||||||
|
{
|
||||||
|
if (targetScroll > -1)
|
||||||
|
{
|
||||||
|
float distance = Math.Abs(targetScroll - BarScroll);
|
||||||
|
float speed = Math.Max(distance * BarSize, 0.1f);
|
||||||
|
BarScroll = (1.0f - speed) * BarScroll + speed * targetScroll;
|
||||||
|
if (MathUtils.NearlyEqual(BarScroll, targetScroll) || GUIScrollBar.DraggingBar != null)
|
||||||
|
{
|
||||||
|
targetScroll = -1;
|
||||||
|
pendingScroll = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((GUI.IsMouseOn(this) || GUI.IsMouseOn(ScrollBar)) && AllowMouseWheelScroll && PlayerInput.ScrollWheelSpeed != 0)
|
||||||
|
{
|
||||||
|
float speed = PlayerInput.ScrollWheelSpeed / 500.0f * BarSize;
|
||||||
|
if (SmoothScroll)
|
||||||
|
{
|
||||||
|
if (ClampScrollToElements)
|
||||||
|
{
|
||||||
|
bool scrollDown = Math.Clamp(PlayerInput.ScrollWheelSpeed, 0, 1) > 0;
|
||||||
|
|
||||||
|
if (scrollDown)
|
||||||
|
{
|
||||||
|
SelectPrevious(takeKeyBoardFocus: true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SelectNext(takeKeyBoardFocus: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pendingScroll = null;
|
||||||
|
if (targetScroll < 0) { targetScroll = BarScroll; }
|
||||||
|
targetScroll -= speed;
|
||||||
|
targetScroll = Math.Clamp(targetScroll, ScrollBar.MinValue, ScrollBar.MaxValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ScrollBar.BarScroll -= (PlayerInput.ScrollWheelSpeed / 500.0f) * BarSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ScrollBar.Enabled = ScrollBarEnabled && BarSize < 1.0f;
|
ScrollBar.Enabled = ScrollBarEnabled && BarSize < 1.0f;
|
||||||
if (AutoHideScrollBar)
|
if (AutoHideScrollBar)
|
||||||
{
|
{
|
||||||
@@ -553,35 +748,47 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SelectNext(bool force = false, bool autoScroll = true)
|
public void SelectNext(bool force = false, bool autoScroll = true, bool takeKeyBoardFocus = false)
|
||||||
{
|
{
|
||||||
int index = SelectedIndex + 1;
|
int index = SelectedIndex + 1;
|
||||||
while (index < Content.CountChildren)
|
while (index < Content.CountChildren)
|
||||||
{
|
{
|
||||||
if (Content.GetChild(index).Visible)
|
GUIComponent child = Content.GetChild(index);
|
||||||
|
if (child.Visible)
|
||||||
{
|
{
|
||||||
Select(index, force, autoScroll);
|
Select(index, force, !SmoothScroll && autoScroll, takeKeyBoardFocus: takeKeyBoardFocus);
|
||||||
|
if (SmoothScroll)
|
||||||
|
{
|
||||||
|
pendingScroll = child;
|
||||||
|
ScrollToElement(child);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SelectPrevious(bool force = false, bool autoScroll = true)
|
public void SelectPrevious(bool force = false, bool autoScroll = true, bool takeKeyBoardFocus = false)
|
||||||
{
|
{
|
||||||
int index = SelectedIndex - 1;
|
int index = SelectedIndex - 1;
|
||||||
while (index >= 0)
|
while (index >= 0)
|
||||||
{
|
{
|
||||||
if (Content.GetChild(index).Visible)
|
GUIComponent child = Content.GetChild(index);
|
||||||
|
if (child.Visible)
|
||||||
{
|
{
|
||||||
Select(index, force, autoScroll);
|
Select(index, force, !SmoothScroll && autoScroll, takeKeyBoardFocus: takeKeyBoardFocus);
|
||||||
|
if (SmoothScroll)
|
||||||
|
{
|
||||||
|
pendingScroll = child;
|
||||||
|
ScrollToElement(child);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
index--;
|
index--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Select(int childIndex, bool force = false, bool autoScroll = true)
|
public void Select(int childIndex, bool force = false, bool autoScroll = true, bool takeKeyBoardFocus = false)
|
||||||
{
|
{
|
||||||
if (childIndex >= Content.CountChildren || childIndex < 0) { return; }
|
if (childIndex >= Content.CountChildren || childIndex < 0) { return; }
|
||||||
|
|
||||||
@@ -646,7 +853,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If one of the children is the subscriber, we don't want to register, because it will unregister the child.
|
// If one of the children is the subscriber, we don't want to register, because it will unregister the child.
|
||||||
if (RectTransform.GetAllChildren().None(rt => rt.GUIComponent == GUI.KeyboardDispatcher.Subscriber))
|
if (takeKeyBoardFocus && RectTransform.GetAllChildren().None(rt => rt.GUIComponent == GUI.KeyboardDispatcher.Subscriber))
|
||||||
{
|
{
|
||||||
Selected = true;
|
Selected = true;
|
||||||
GUI.KeyboardDispatcher.Subscriber = this;
|
GUI.KeyboardDispatcher.Subscriber = this;
|
||||||
@@ -712,6 +919,14 @@ namespace Barotrauma
|
|||||||
totalSize += (ScrollBar.IsHorizontal) ? child.Rect.Width : child.Rect.Height;
|
totalSize += (ScrollBar.IsHorizontal) ? child.Rect.Width : child.Rect.Height;
|
||||||
}
|
}
|
||||||
totalSize += Content.CountChildren * Spacing;
|
totalSize += Content.CountChildren * Spacing;
|
||||||
|
if (PadBottom)
|
||||||
|
{
|
||||||
|
GUIComponent last = Content.Children.LastOrDefault();
|
||||||
|
if (last != null)
|
||||||
|
{
|
||||||
|
totalSize += Rect.Height - last.Rect.Height;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float minScrollBarSize = 20.0f;
|
float minScrollBarSize = 20.0f;
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public GUIMessage(string text, Color color, float lifeTime, ScalableFont font = null)
|
public GUIMessage(string text, Color color, float lifeTime, ScalableFont font = null)
|
||||||
{
|
{
|
||||||
coloredText = new ColoredText(text, color, false);
|
coloredText = new ColoredText(text, color, false, false);
|
||||||
this.lifeTime = lifeTime;
|
this.lifeTime = lifeTime;
|
||||||
Timer = lifeTime;
|
Timer = lifeTime;
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public GUIMessage(string text, Color color, Vector2 worldPosition, Vector2 velocity, float lifeTime, Alignment textAlignment = Alignment.Center, ScalableFont font = null)
|
public GUIMessage(string text, Color color, Vector2 worldPosition, Vector2 velocity, float lifeTime, Alignment textAlignment = Alignment.Center, ScalableFont font = null)
|
||||||
{
|
{
|
||||||
coloredText = new ColoredText(text, color, false);
|
coloredText = new ColoredText(text, color, false, false);
|
||||||
WorldSpace = true;
|
WorldSpace = true;
|
||||||
pos = worldPosition;
|
pos = worldPosition;
|
||||||
Timer = lifeTime;
|
Timer = lifeTime;
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ namespace Barotrauma
|
|||||||
public GUITextBlock Header { get; private set; }
|
public GUITextBlock Header { get; private set; }
|
||||||
public GUITextBlock Text { get; private set; }
|
public GUITextBlock Text { get; private set; }
|
||||||
public string Tag { get; private set; }
|
public string Tag { get; private set; }
|
||||||
|
public bool Closed { get; private set; }
|
||||||
|
|
||||||
public GUIImage Icon
|
public GUIImage Icon
|
||||||
{
|
{
|
||||||
@@ -47,9 +48,16 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool alwaysVisible;
|
public GUIImage BackgroundIcon { get; private set; }
|
||||||
|
private GUIImage newBackgroundIcon;
|
||||||
|
|
||||||
|
public bool AutoClose;
|
||||||
|
|
||||||
|
private readonly bool alwaysVisible;
|
||||||
|
|
||||||
private float openState;
|
private float openState;
|
||||||
|
private float iconState;
|
||||||
|
private bool iconSwitching;
|
||||||
private bool closing;
|
private bool closing;
|
||||||
|
|
||||||
private Type type;
|
private Type type;
|
||||||
@@ -62,7 +70,7 @@ namespace Barotrauma
|
|||||||
this.Buttons[0].OnClicked = Close;
|
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)
|
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)
|
||||||
: base(new RectTransform(GUI.Canvas.RelativeSize, GUI.Canvas, Anchor.Center), style: GUI.Style.GetComponentStyle("GUIMessageBox." + type) != null ? "GUIMessageBox." + type : "GUIMessageBox")
|
: base(new RectTransform(GUI.Canvas.RelativeSize, GUI.Canvas, Anchor.Center), style: GUI.Style.GetComponentStyle("GUIMessageBox." + type) != null ? "GUIMessageBox." + type : "GUIMessageBox")
|
||||||
{
|
{
|
||||||
int width = (int)(DefaultWidth * (type == Type.Default ? 1.0f : 1.5f)), height = 0;
|
int width = (int)(DefaultWidth * (type == Type.Default ? 1.0f : 1.5f)), height = 0;
|
||||||
@@ -80,6 +88,15 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (backgroundIcon != null)
|
||||||
|
{
|
||||||
|
BackgroundIcon = new GUIImage(new RectTransform(backgroundIcon.size.ToPoint(), RectTransform), backgroundIcon)
|
||||||
|
{
|
||||||
|
IgnoreLayoutGroups = true,
|
||||||
|
Color = Color.Transparent
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
InnerFrame = new GUIFrame(new RectTransform(new Point(width, height), RectTransform, type == Type.InGame ? Anchor.TopCenter : Anchor.Center) { IsFixedSize = false }, style: null);
|
InnerFrame = new GUIFrame(new RectTransform(new Point(width, height), RectTransform, type == Type.InGame ? Anchor.TopCenter : Anchor.Center) { IsFixedSize = false }, style: null);
|
||||||
GUI.Style.Apply(InnerFrame, "", this);
|
GUI.Style.Apply(InnerFrame, "", this);
|
||||||
this.type = type;
|
this.type = type;
|
||||||
@@ -145,6 +162,7 @@ namespace Barotrauma
|
|||||||
InnerFrame.RectTransform.AbsoluteOffset = new Point(0, GameMain.GraphicsHeight);
|
InnerFrame.RectTransform.AbsoluteOffset = new Point(0, GameMain.GraphicsHeight);
|
||||||
alwaysVisible = true;
|
alwaysVisible = true;
|
||||||
CanBeFocused = false;
|
CanBeFocused = false;
|
||||||
|
AutoClose = true;
|
||||||
GUI.Style.Apply(InnerFrame, "", this);
|
GUI.Style.Apply(InnerFrame, "", this);
|
||||||
|
|
||||||
var horizontalLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 0.95f), InnerFrame.RectTransform, Anchor.Center),
|
var horizontalLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 0.95f), InnerFrame.RectTransform, Anchor.Center),
|
||||||
@@ -157,6 +175,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Icon = new GUIImage(new RectTransform(new Vector2(0.2f, 0.95f), horizontalLayoutGroup.RectTransform), icon, scaleToFit: true);
|
Icon = new GUIImage(new RectTransform(new Vector2(0.2f, 0.95f), horizontalLayoutGroup.RectTransform), icon, scaleToFit: true);
|
||||||
}
|
}
|
||||||
|
else if (iconStyle != string.Empty)
|
||||||
|
{
|
||||||
|
Icon = new GUIImage(new RectTransform(new Vector2(0.2f, 0.95f), horizontalLayoutGroup.RectTransform), iconStyle, scaleToFit: true);
|
||||||
|
}
|
||||||
|
|
||||||
Content = new GUILayoutGroup(new RectTransform(new Vector2(icon != null ? 0.65f : 0.85f, 1.0f), horizontalLayoutGroup.RectTransform));
|
Content = new GUILayoutGroup(new RectTransform(new Vector2(icon != null ? 0.65f : 0.85f, 1.0f), horizontalLayoutGroup.RectTransform));
|
||||||
|
|
||||||
@@ -182,6 +204,10 @@ namespace Barotrauma
|
|||||||
Text.RectTransform.NonScaledSize = Text.RectTransform.MinSize = Text.RectTransform.MaxSize =
|
Text.RectTransform.NonScaledSize = Text.RectTransform.MinSize = Text.RectTransform.MaxSize =
|
||||||
new Point(Text.Rect.Width, Text.Rect.Height);
|
new Point(Text.Rect.Width, Text.Rect.Height);
|
||||||
Text.RectTransform.IsFixedSize = true;
|
Text.RectTransform.IsFixedSize = true;
|
||||||
|
if (string.IsNullOrWhiteSpace(headerText))
|
||||||
|
{
|
||||||
|
Content.ChildAnchor = Anchor.Center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (height == 0)
|
if (height == 0)
|
||||||
@@ -226,6 +252,23 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetBackgroundIcon(Sprite icon)
|
||||||
|
{
|
||||||
|
if (icon == null) { return; }
|
||||||
|
GUIImage newIcon = new GUIImage(new RectTransform(icon.size.ToPoint(), RectTransform), icon)
|
||||||
|
{
|
||||||
|
IgnoreLayoutGroups = true,
|
||||||
|
Color = Color.Transparent
|
||||||
|
};
|
||||||
|
|
||||||
|
if (newBackgroundIcon != null)
|
||||||
|
{
|
||||||
|
RemoveChild(newBackgroundIcon);
|
||||||
|
newBackgroundIcon = null;
|
||||||
|
}
|
||||||
|
newBackgroundIcon = newIcon;
|
||||||
|
}
|
||||||
|
|
||||||
protected override void Update(float deltaTime)
|
protected override void Update(float deltaTime)
|
||||||
{
|
{
|
||||||
if (type == Type.InGame)
|
if (type == Type.InGame)
|
||||||
@@ -246,10 +289,19 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (!closing)
|
if (!closing)
|
||||||
{
|
{
|
||||||
InnerFrame.RectTransform.AbsoluteOffset = Vector2.SmoothStep(initialPos, defaultPos, openState).ToPoint();
|
Point step = Vector2.SmoothStep(initialPos, defaultPos, openState).ToPoint();
|
||||||
|
InnerFrame.RectTransform.AbsoluteOffset = step;
|
||||||
|
if (BackgroundIcon != null)
|
||||||
|
{
|
||||||
|
BackgroundIcon.RectTransform.AbsoluteOffset = new Point(InnerFrame.Rect.Location.X - (int) (BackgroundIcon.Rect.Size.X / 1.25f), (int)defaultPos.Y - BackgroundIcon.Rect.Size.Y / 2);
|
||||||
|
if (!MathUtils.NearlyEqual(openState, 1.0f))
|
||||||
|
{
|
||||||
|
BackgroundIcon.Color = ToolBox.GradientLerp(openState, Color.Transparent, Color.White);
|
||||||
|
}
|
||||||
|
}
|
||||||
openState = Math.Min(openState + deltaTime * 2.0f, 1.0f);
|
openState = Math.Min(openState + deltaTime * 2.0f, 1.0f);
|
||||||
|
|
||||||
if (GUI.MouseOn != InnerFrame && !InnerFrame.IsParentOf(GUI.MouseOn))
|
if (GUI.MouseOn != InnerFrame && !InnerFrame.IsParentOf(GUI.MouseOn) && AutoClose)
|
||||||
{
|
{
|
||||||
inGameCloseTimer += deltaTime;
|
inGameCloseTimer += deltaTime;
|
||||||
}
|
}
|
||||||
@@ -262,13 +314,55 @@ namespace Barotrauma
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
openState += deltaTime * 2.0f;
|
openState += deltaTime * 2.0f;
|
||||||
InnerFrame.RectTransform.AbsoluteOffset = Vector2.SmoothStep(defaultPos, endPos, openState - 1.0f).ToPoint();
|
Point step = Vector2.SmoothStep(defaultPos, endPos, openState - 1.0f).ToPoint();
|
||||||
|
InnerFrame.RectTransform.AbsoluteOffset = step;
|
||||||
|
if (BackgroundIcon != null)
|
||||||
|
{
|
||||||
|
BackgroundIcon.Color *= 0.9f;
|
||||||
|
}
|
||||||
if (openState >= 2.0f)
|
if (openState >= 2.0f)
|
||||||
{
|
{
|
||||||
if (Parent != null) { Parent.RemoveChild(this); }
|
if (Parent != null) { Parent.RemoveChild(this); }
|
||||||
if (MessageBoxes.Contains(this)) { MessageBoxes.Remove(this); }
|
if (MessageBoxes.Contains(this)) { MessageBoxes.Remove(this); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (newBackgroundIcon != null)
|
||||||
|
{
|
||||||
|
if (!iconSwitching)
|
||||||
|
{
|
||||||
|
if (BackgroundIcon != null)
|
||||||
|
{
|
||||||
|
BackgroundIcon.Color *= 0.9f;
|
||||||
|
if (BackgroundIcon.Color.A == 0)
|
||||||
|
{
|
||||||
|
BackgroundIcon = null;
|
||||||
|
iconSwitching = true;
|
||||||
|
RemoveChild(BackgroundIcon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iconSwitching = true;
|
||||||
|
}
|
||||||
|
iconState = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newBackgroundIcon.SetAsFirstChild();
|
||||||
|
newBackgroundIcon.RectTransform.AbsoluteOffset = new Point(InnerFrame.Rect.Location.X - (int) (newBackgroundIcon.Rect.Size.X / 1.25f), (int)defaultPos.Y - newBackgroundIcon.Rect.Size.Y / 2);
|
||||||
|
newBackgroundIcon.Color = ToolBox.GradientLerp(iconState, Color.Transparent, Color.White);
|
||||||
|
if (newBackgroundIcon.Color.A == 255)
|
||||||
|
{
|
||||||
|
BackgroundIcon = newBackgroundIcon;
|
||||||
|
BackgroundIcon.SetAsFirstChild();
|
||||||
|
newBackgroundIcon = null;
|
||||||
|
iconSwitching = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
iconState = Math.Min(iconState + deltaTime * 2.0f, 1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,6 +378,8 @@ namespace Barotrauma
|
|||||||
if (Parent != null) { Parent.RemoveChild(this); }
|
if (Parent != null) { Parent.RemoveChild(this); }
|
||||||
if (MessageBoxes.Contains(this)) { MessageBoxes.Remove(this); }
|
if (MessageBoxes.Contains(this)) { MessageBoxes.Remove(this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Closed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Close(GUIButton button, object obj)
|
public bool Close(GUIButton button, object obj)
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ namespace Barotrauma
|
|||||||
private float pressedDelay = 0.5f;
|
private float pressedDelay = 0.5f;
|
||||||
private bool IsPressedTimerRunning { get { return pressedTimer > 0; } }
|
private bool IsPressedTimerRunning { get { return pressedTimer > 0; } }
|
||||||
|
|
||||||
public GUINumberInput(RectTransform rectT, NumberType inputType, string style = "", Alignment textAlignment = Alignment.Center, float? relativeButtonAreaWidth = null) : base(style, rectT)
|
public GUINumberInput(RectTransform rectT, NumberType inputType, string style = "", Alignment textAlignment = Alignment.Center, float? relativeButtonAreaWidth = null, bool hidePlusMinusButtons = false) : base(style, rectT)
|
||||||
{
|
{
|
||||||
LayoutGroup = new GUILayoutGroup(new RectTransform(Vector2.One, rectT), isHorizontal: true, childAnchor: Anchor.CenterLeft) { Stretch = true };
|
LayoutGroup = new GUILayoutGroup(new RectTransform(Vector2.One, rectT), isHorizontal: true, childAnchor: Anchor.CenterLeft) { Stretch = true };
|
||||||
|
|
||||||
@@ -235,7 +235,7 @@ namespace Barotrauma
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (inputType != NumberType.Int)
|
if (inputType != NumberType.Int || hidePlusMinusButtons)
|
||||||
{
|
{
|
||||||
HidePlusMinusButtons();
|
HidePlusMinusButtons();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ namespace Barotrauma
|
|||||||
(int)(Rect.Width - style.Padding.X + style.Padding.Z),
|
(int)(Rect.Width - style.Padding.X + style.Padding.Z),
|
||||||
(int)(Rect.Height - style.Padding.Y + style.Padding.W));
|
(int)(Rect.Height - style.Padding.Y + style.Padding.W));
|
||||||
frame.Visible = showFrame;
|
frame.Visible = showFrame;
|
||||||
slider.Visible = true;
|
slider.Visible = BarSize > 0.0f;
|
||||||
|
|
||||||
if (showFrame)
|
if (showFrame)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ namespace Barotrauma
|
|||||||
public UISprite UIGlow { get; private set; }
|
public UISprite UIGlow { get; private set; }
|
||||||
public UISprite UIGlowCircular { get; private set; }
|
public UISprite UIGlowCircular { get; private set; }
|
||||||
|
|
||||||
|
public UISprite ButtonPulse { get; private set; }
|
||||||
|
|
||||||
public SpriteSheet FocusIndicator { get; private set; }
|
public SpriteSheet FocusIndicator { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -206,6 +208,9 @@ namespace Barotrauma
|
|||||||
case "uiglowcircular":
|
case "uiglowcircular":
|
||||||
UIGlowCircular = new UISprite(subElement);
|
UIGlowCircular = new UISprite(subElement);
|
||||||
break;
|
break;
|
||||||
|
case "endroundbuttonpulse":
|
||||||
|
ButtonPulse = new UISprite(subElement);
|
||||||
|
break;
|
||||||
case "focusindicator":
|
case "focusindicator":
|
||||||
FocusIndicator = new SpriteSheet(subElement);
|
FocusIndicator = new SpriteSheet(subElement);
|
||||||
break;
|
break;
|
||||||
@@ -255,7 +260,8 @@ namespace Barotrauma
|
|||||||
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);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
GameMain.Instance.OnResolutionChanged += () => { RescaleElements(); };
|
// TODO: Needs to unregister if we ever remove GUIStyles.
|
||||||
|
GameMain.Instance.ResolutionChanged += RescaleElements;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -272,6 +272,8 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
public List<ClickableArea> ClickableAreas { get; private set; } = new List<ClickableArea>();
|
public List<ClickableArea> ClickableAreas { get; private set; } = new List<ClickableArea>();
|
||||||
|
|
||||||
|
public bool Shadow { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is the new constructor.
|
/// This is the new constructor.
|
||||||
/// If the rectT height is set 0, the height is calculated from the text.
|
/// If the rectT height is set 0, the height is calculated from the text.
|
||||||
@@ -320,10 +322,10 @@ namespace Barotrauma
|
|||||||
hasColorHighlight = richTextData != null;
|
hasColorHighlight = richTextData != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CalculateHeightFromText(int padding = 0)
|
public void CalculateHeightFromText(int padding = 0, bool removeExtraSpacing = false)
|
||||||
{
|
{
|
||||||
if (wrappedText == null) { return; }
|
if (wrappedText == null) { return; }
|
||||||
RectTransform.Resize(new Point(RectTransform.Rect.Width, (int)Font.MeasureString(wrappedText).Y + padding));
|
RectTransform.Resize(new Point(RectTransform.Rect.Width, (int)Font.MeasureString(wrappedText, removeExtraSpacing).Y + padding));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ApplyStyle(GUIComponentStyle componentStyle)
|
public override void ApplyStyle(GUIComponentStyle componentStyle)
|
||||||
@@ -443,8 +445,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
protected override void SetAlpha(float a)
|
protected override void SetAlpha(float a)
|
||||||
{
|
{
|
||||||
base.SetAlpha(a);
|
// base.SetAlpha(a);
|
||||||
textColor = new Color(textColor.R, textColor.G, textColor.B, a);
|
textColor = new Color(TextColor.R / 255.0f, TextColor.G / 255.0f, TextColor.B / 255.0f, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -626,12 +628,17 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (!hasColorHighlight)
|
if (!hasColorHighlight)
|
||||||
{
|
{
|
||||||
Font.DrawString(spriteBatch,
|
string textToShow = Censor ? censoredText : (Wrap ? wrappedText : text);
|
||||||
Censor ? censoredText : (Wrap ? wrappedText : text),
|
Color colorToShow = currentTextColor * (currentTextColor.A / 255.0f);
|
||||||
pos,
|
|
||||||
currentTextColor * (currentTextColor.A / 255.0f),
|
if (Shadow)
|
||||||
0.0f, origin, TextScale,
|
{
|
||||||
SpriteEffects.None, textDepth);
|
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, colorToShow, 0.0f, origin, TextScale, SpriteEffects.None, textDepth);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -134,6 +134,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
textBlock.OverflowClip = value != null;
|
textBlock.OverflowClip = value != null;
|
||||||
maxTextLength = value;
|
maxTextLength = value;
|
||||||
|
if (Text.Length > MaxTextLength)
|
||||||
|
{
|
||||||
|
SetText(textBlock.Text.Substring(0, (int)maxTextLength));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,6 +364,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
CaretIndex = Math.Min(CaretIndex, textDrawn.Length);
|
||||||
textDrawn = Censor ? textBlock.CensoredText : textBlock.Text;
|
textDrawn = Censor ? textBlock.CensoredText : textBlock.Text;
|
||||||
Vector2 textSize = Font.MeasureString(textDrawn.Substring(0, CaretIndex));
|
Vector2 textSize = Font.MeasureString(textDrawn.Substring(0, CaretIndex));
|
||||||
caretPos = new Vector2(textSize.X, 0) + textBlock.TextPos - textBlock.Origin;
|
caretPos = new Vector2(textSize.X, 0) + textBlock.TextPos - textBlock.Origin;
|
||||||
|
|||||||
@@ -75,6 +75,11 @@ namespace Barotrauma
|
|||||||
get; private set;
|
get; private set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Rectangle VotingArea
|
||||||
|
{
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
public static int Padding
|
public static int Padding
|
||||||
{
|
{
|
||||||
get; private set;
|
get; private set;
|
||||||
@@ -84,7 +89,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (GameMain.Instance != null)
|
if (GameMain.Instance != null)
|
||||||
{
|
{
|
||||||
GameMain.Instance.OnResolutionChanged += CreateAreas;
|
GameMain.Instance.ResolutionChanged += CreateAreas;
|
||||||
GameMain.Config.OnHUDScaleChanged += CreateAreas;
|
GameMain.Config.OnHUDScaleChanged += CreateAreas;
|
||||||
CreateAreas();
|
CreateAreas();
|
||||||
CharacterInfo.Init();
|
CharacterInfo.Init();
|
||||||
@@ -144,6 +149,13 @@ namespace Barotrauma
|
|||||||
int healthWindowY = GameMain.GraphicsHeight / 2 - healthWindowHeight / 2;
|
int healthWindowY = GameMain.GraphicsHeight / 2 - healthWindowHeight / 2;
|
||||||
|
|
||||||
HealthWindowAreaLeft = new Rectangle(healthWindowX, healthWindowY, healthWindowWidth, healthWindowHeight);
|
HealthWindowAreaLeft = new Rectangle(healthWindowX, healthWindowY, healthWindowWidth, healthWindowHeight);
|
||||||
|
|
||||||
|
int votingAreaWidth = (int)(400 * GUI.Scale);
|
||||||
|
int votingAreaX = GameMain.GraphicsWidth - Padding - votingAreaWidth;
|
||||||
|
int votingAreaY = Padding + ButtonAreaTop.Height;
|
||||||
|
|
||||||
|
// Height is based on text content
|
||||||
|
VotingArea = new Rectangle(votingAreaX, votingAreaY, votingAreaWidth, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Draw(SpriteBatch spriteBatch)
|
public static void Draw(SpriteBatch spriteBatch)
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ namespace Barotrauma
|
|||||||
float noiseStrength = (float)PerlinNoise.CalculatePerlin(noiseT, noiseT, 0);
|
float noiseStrength = (float)PerlinNoise.CalculatePerlin(noiseT, noiseT, 0);
|
||||||
float noiseScale = (float)PerlinNoise.CalculatePerlin(noiseT * 5.0f, noiseT * 2.0f, 0) * 4.0f;
|
float noiseScale = (float)PerlinNoise.CalculatePerlin(noiseT * 5.0f, noiseT * 2.0f, 0) * 4.0f;
|
||||||
noiseSprite.DrawTiled(spriteBatch, Vector2.Zero, new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight),
|
noiseSprite.DrawTiled(spriteBatch, Vector2.Zero, new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight),
|
||||||
startOffset: new Point(Rand.Range(0, noiseSprite.SourceRect.Width), Rand.Range(0, noiseSprite.SourceRect.Height)),
|
startOffset: new Vector2(Rand.Range(0.0f, noiseSprite.SourceRect.Width), Rand.Range(0.0f, noiseSprite.SourceRect.Height)),
|
||||||
color: Color.White * noiseStrength * 0.1f,
|
color: Color.White * noiseStrength * 0.1f,
|
||||||
textureScale: Vector2.One * noiseScale);
|
textureScale: Vector2.One * noiseScale);
|
||||||
|
|
||||||
@@ -185,7 +185,7 @@ namespace Barotrauma
|
|||||||
if (LoadState == 100.0f)
|
if (LoadState == 100.0f)
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
if (GameMain.Config.AutomaticQuickStartEnabled && GameMain.FirstLoad)
|
if (GameMain.Config.AutomaticQuickStartEnabled || GameMain.Config.AutomaticCampaignLoadEnabled && GameMain.FirstLoad)
|
||||||
{
|
{
|
||||||
loadText = "QUICKSTARTING ...";
|
loadText = "QUICKSTARTING ...";
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,683 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
class SubmarineSelection
|
||||||
|
{
|
||||||
|
private const int submarinesPerPage = 4;
|
||||||
|
private int currentPage = 1;
|
||||||
|
private int pageCount;
|
||||||
|
private bool transferService, purchaseService, initialized;
|
||||||
|
private int deliveryFee;
|
||||||
|
private string deliveryLocationName;
|
||||||
|
|
||||||
|
public GUIFrame GuiFrame;
|
||||||
|
private GUIFrame pageIndicatorHolder;
|
||||||
|
private GUICustomComponent selectedSubmarineIndicator;
|
||||||
|
private GUILayoutGroup submarineHorizontalGroup, submarineControlsGroup;
|
||||||
|
private GUIButton browseLeftButton, browseRightButton, confirmButton, confirmButtonAlt;
|
||||||
|
private GUIListBox specsFrame;
|
||||||
|
private GUIImage[] pageIndicators;
|
||||||
|
private GUITextBlock descriptionTextBlock;
|
||||||
|
private int selectionIndicatorThickness;
|
||||||
|
private GUIImage listBackground;
|
||||||
|
|
||||||
|
private List<SubmarineInfo> subsToShow;
|
||||||
|
private SubmarineDisplayContent[] submarineDisplays = new SubmarineDisplayContent[submarinesPerPage];
|
||||||
|
private SubmarineInfo selectedSubmarine = null;
|
||||||
|
private string purchaseAndSwitchText, purchaseOnlyText, deliveryText, currentSubText, deliveryFeeText, priceText, switchText, missingPreviewText, currencyShorthandText, currencyLongText;
|
||||||
|
private RectTransform parent;
|
||||||
|
private 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 string[] messageBoxOptions;
|
||||||
|
|
||||||
|
public const int DeliveryFeePerDistanceTravelled = 1000;
|
||||||
|
public static bool ContentRefreshRequired = false;
|
||||||
|
|
||||||
|
private static readonly Color indicatorColor = new Color(112, 149, 129);
|
||||||
|
private Point createdForResolution;
|
||||||
|
|
||||||
|
private struct SubmarineDisplayContent
|
||||||
|
{
|
||||||
|
public GUIFrame background;
|
||||||
|
public GUIImage submarineImage;
|
||||||
|
public SubmarineInfo displayedSubmarine;
|
||||||
|
public GUITextBlock submarineName;
|
||||||
|
public GUITextBlock submarineClass;
|
||||||
|
public GUITextBlock submarineFee;
|
||||||
|
public GUIButton selectSubmarineButton;
|
||||||
|
public GUITextBlock middleTextBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubmarineSelection(bool transfer, Action closeAction, RectTransform parent)
|
||||||
|
{
|
||||||
|
if (GameMain.GameSession.Campaign == null) return;
|
||||||
|
|
||||||
|
transferService = transfer;
|
||||||
|
purchaseService = !transfer;
|
||||||
|
this.parent = parent;
|
||||||
|
this.closeAction = closeAction;
|
||||||
|
|
||||||
|
subsToShow = new List<SubmarineInfo>();
|
||||||
|
|
||||||
|
if (GameMain.Client == null)
|
||||||
|
{
|
||||||
|
messageBoxOptions = new string[2] { TextManager.Get("Yes"), TextManager.Get("Cancel") };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
messageBoxOptions = new string[2] { TextManager.Get("Yes") + " " + TextManager.Get("initiatevoting"), TextManager.Get("Cancel") };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Submarine.MainSub?.Info == null) return;
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Initialize()
|
||||||
|
{
|
||||||
|
initialized = true;
|
||||||
|
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();
|
||||||
|
|
||||||
|
UpdateSubmarines();
|
||||||
|
missingPreviewText = TextManager.Get("SubPreviewImageNotFound");
|
||||||
|
CreateGUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int CalculateDeliveryFee()
|
||||||
|
{
|
||||||
|
int distanceToOutpost = GameMain.GameSession.Map.DistanceToClosestLocationWithOutpost(GameMain.GameSession.Map.CurrentLocation, out Location endLocation);
|
||||||
|
deliveryLocationName = endLocation.Name;
|
||||||
|
return DeliveryFeePerDistanceTravelled * distanceToOutpost;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateGUI()
|
||||||
|
{
|
||||||
|
createdForResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||||
|
|
||||||
|
GUILayoutGroup content;
|
||||||
|
GuiFrame = new GUIFrame(new RectTransform(new Vector2(0.75f, 0.7f), parent, Anchor.TopCenter, Pivot.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.02f) });
|
||||||
|
selectionIndicatorThickness = HUDLayoutSettings.Padding / 2;
|
||||||
|
|
||||||
|
GUIFrame background = new GUIFrame(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center), color: Color.Black * 0.9f)
|
||||||
|
{
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
header.CalculateHeightFromText(0, true);
|
||||||
|
GUITextBlock credits = new GUITextBlock(new RectTransform(Vector2.One, header.RectTransform), "", font: GUI.SubHeadingFont, textAlignment: Alignment.CenterRight)
|
||||||
|
{
|
||||||
|
TextGetter = CampaignUI.GetMoney
|
||||||
|
};
|
||||||
|
|
||||||
|
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), content.RectTransform), style: "HorizontalLine");
|
||||||
|
|
||||||
|
GUILayoutGroup submarineContentGroup = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.4f), content.RectTransform)) { AbsoluteSpacing = HUDLayoutSettings.Padding, Stretch = true };
|
||||||
|
submarineHorizontalGroup = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.9f), submarineContentGroup.RectTransform)) { IsHorizontal = true, AbsoluteSpacing = HUDLayoutSettings.Padding, Stretch = true };
|
||||||
|
|
||||||
|
submarineControlsGroup = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.1f), submarineContentGroup.RectTransform), true, Anchor.TopCenter);
|
||||||
|
|
||||||
|
GUILayoutGroup infoFrame = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.4f), content.RectTransform)) { IsHorizontal = true, Stretch = true, AbsoluteSpacing = HUDLayoutSettings.Padding };
|
||||||
|
new GUIFrame(new RectTransform(Vector2.One, infoFrame.RectTransform), style: null, new Color(8, 13, 19)) { IgnoreLayoutGroups = true };
|
||||||
|
listBackground = new GUIImage(new RectTransform(new Vector2(0.59f, 1f), infoFrame.RectTransform, Anchor.CenterRight), style: null, true)
|
||||||
|
{
|
||||||
|
IgnoreLayoutGroups = true
|
||||||
|
};
|
||||||
|
new GUIListBox(new RectTransform(Vector2.One, infoFrame.RectTransform)) { IgnoreLayoutGroups = true, CanBeFocused = false };
|
||||||
|
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 };
|
||||||
|
|
||||||
|
GUILayoutGroup buttonFrame = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.075f), content.RectTransform), childAnchor: Anchor.CenterRight) { IsHorizontal = true, AbsoluteSpacing = HUDLayoutSettings.Padding };
|
||||||
|
|
||||||
|
if (closeAction != null)
|
||||||
|
{
|
||||||
|
GUIButton closeButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1f), buttonFrame.RectTransform), TextManager.Get("Close"), style: "GUIButtonFreeScale")
|
||||||
|
{
|
||||||
|
OnClicked = (button, userData) =>
|
||||||
|
{
|
||||||
|
closeAction();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (purchaseService) confirmButtonAlt = new GUIButton(new RectTransform(new Vector2(0.2f, 1f), buttonFrame.RectTransform), purchaseOnlyText, style: "GUIButtonFreeScale");
|
||||||
|
confirmButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1f), buttonFrame.RectTransform), purchaseService ? purchaseAndSwitchText : deliveryFee > 0 ? deliveryText : switchText, style: "GUIButtonFreeScale");
|
||||||
|
SetConfirmButtonState(false);
|
||||||
|
|
||||||
|
pageIndicatorHolder = new GUIFrame(new RectTransform(new Vector2(1f, 1.5f), submarineControlsGroup.RectTransform), style: null);
|
||||||
|
pageIndicator = GUI.Style.GetComponentStyle("GUIPageIndicator").GetDefaultSprite();
|
||||||
|
UpdatePaging();
|
||||||
|
|
||||||
|
for (int i = 0; i < submarineDisplays.Length; i++)
|
||||||
|
{
|
||||||
|
SubmarineDisplayContent submarineDisplayElement = new SubmarineDisplayContent();
|
||||||
|
submarineDisplayElement.background = new GUIFrame(new RectTransform(new Vector2(1f / submarinesPerPage, 1f), submarineHorizontalGroup.RectTransform), style: null, new Color(8, 13, 19));
|
||||||
|
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.selectSubmarineButton = new GUIButton(new RectTransform(Vector2.One, submarineDisplayElement.background.RectTransform), style: null);
|
||||||
|
submarineDisplays[i] = submarineDisplayElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedSubmarineIndicator = new GUICustomComponent(new RectTransform(Point.Zero, submarineHorizontalGroup.RectTransform), onDraw: (sb, component) => DrawSubmarineIndicator(sb, component.Rect)) { IgnoreLayoutGroups = true, CanBeFocused = false };
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdatePaging()
|
||||||
|
{
|
||||||
|
if (pageIndicatorHolder == null) return;
|
||||||
|
pageIndicatorHolder.ClearChildren();
|
||||||
|
if (currentPage > pageCount) currentPage = pageCount;
|
||||||
|
if (pageCount < 2) return;
|
||||||
|
|
||||||
|
browseLeftButton = new GUIButton(new RectTransform(new Vector2(1.15f, 1.15f), pageIndicatorHolder.RectTransform, Anchor.CenterLeft, Pivot.CenterRight) { AbsoluteOffset = new Point(-HUDLayoutSettings.Padding * 3, 0) }, string.Empty, style: "GUIButtonToggleLeft")
|
||||||
|
{
|
||||||
|
IgnoreLayoutGroups = true,
|
||||||
|
OnClicked = (button, userData) =>
|
||||||
|
{
|
||||||
|
ChangePage(-1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Point indicatorSize = new Point(GUI.IntScale(pageIndicator.SourceRect.Width * 1.5f), GUI.IntScale(pageIndicator.SourceRect.Height * 1.5f));
|
||||||
|
pageIndicatorHolder.RectTransform.NonScaledSize = new Point(pageCount * indicatorSize.X + HUDLayoutSettings.Padding * (pageCount - 1), pageIndicatorHolder.RectTransform.NonScaledSize.Y);
|
||||||
|
|
||||||
|
int xPos = 0;
|
||||||
|
int yPos = pageIndicatorHolder.Rect.Height / 2 - indicatorSize.Y / 2;
|
||||||
|
|
||||||
|
pageIndicators = new GUIImage[pageCount];
|
||||||
|
for (int i = 0; i < pageCount; i++)
|
||||||
|
{
|
||||||
|
pageIndicators[i] = new GUIImage(new RectTransform(indicatorSize, pageIndicatorHolder.RectTransform) { AbsoluteOffset = new Point(xPos, yPos) }, pageIndicator, null, true);
|
||||||
|
xPos += indicatorSize.X + HUDLayoutSettings.Padding;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < pageIndicators.Length; i++)
|
||||||
|
{
|
||||||
|
pageIndicators[i].Color = i == currentPage - 1 ? Color.White : Color.Gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
browseRightButton = new GUIButton(new RectTransform(new Vector2(1.15f, 1.15f), pageIndicatorHolder.RectTransform, Anchor.CenterRight, Pivot.CenterLeft) { AbsoluteOffset = new Point(-HUDLayoutSettings.Padding * 3, 0) }, string.Empty, style: "GUIButtonToggleRight")
|
||||||
|
{
|
||||||
|
IgnoreLayoutGroups = true,
|
||||||
|
OnClicked = (button, userData) =>
|
||||||
|
{
|
||||||
|
ChangePage(1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
browseLeftButton.Enabled = currentPage > 1;
|
||||||
|
browseRightButton.Enabled = currentPage < pageCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawSubmarineIndicator(SpriteBatch spriteBatch, Rectangle area)
|
||||||
|
{
|
||||||
|
if (area == Rectangle.Empty) return;
|
||||||
|
GUI.DrawRectangle(spriteBatch, area, indicatorColor, thickness: selectionIndicatorThickness);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
if (ContentRefreshRequired)
|
||||||
|
{
|
||||||
|
RefreshSubmarineDisplay(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Input
|
||||||
|
if (PlayerInput.KeyHit(Keys.Left))
|
||||||
|
{
|
||||||
|
SelectSubmarine(subsToShow.IndexOf(selectedSubmarine), -1);
|
||||||
|
}
|
||||||
|
else if (PlayerInput.KeyHit(Keys.Right))
|
||||||
|
{
|
||||||
|
SelectSubmarine(subsToShow.IndexOf(selectedSubmarine), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RefreshSubmarineDisplay(bool updateSubs)
|
||||||
|
{
|
||||||
|
if (!initialized) Initialize();
|
||||||
|
if (GameMain.GraphicsWidth != createdForResolution.X || GameMain.GraphicsHeight != createdForResolution.Y) CreateGUI();
|
||||||
|
if (updateSubs) UpdateSubmarines();
|
||||||
|
|
||||||
|
if (pageIndicators != null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < pageIndicators.Length; i++)
|
||||||
|
{
|
||||||
|
pageIndicators[i].Color = i == currentPage - 1 ? Color.White : Color.Gray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int submarineIndex = (currentPage - 1) * submarinesPerPage;
|
||||||
|
|
||||||
|
for (int i = 0; i < submarineDisplays.Length; i++)
|
||||||
|
{
|
||||||
|
SubmarineInfo subToDisplay = GetSubToDisplay(submarineIndex);
|
||||||
|
if (subToDisplay == null)
|
||||||
|
{
|
||||||
|
submarineDisplays[i].submarineImage.Sprite = null;
|
||||||
|
submarineDisplays[i].submarineName.Text = string.Empty;
|
||||||
|
submarineDisplays[i].submarineFee.Text = string.Empty;
|
||||||
|
submarineDisplays[i].submarineClass.Text = string.Empty;
|
||||||
|
submarineDisplays[i].selectSubmarineButton.Enabled = false;
|
||||||
|
submarineDisplays[i].selectSubmarineButton.OnClicked = null;
|
||||||
|
submarineDisplays[i].displayedSubmarine = null;
|
||||||
|
submarineDisplays[i].middleTextBlock.AutoDraw = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
submarineDisplays[i].displayedSubmarine = subToDisplay;
|
||||||
|
Sprite previewImage = GetPreviewImage(subToDisplay);
|
||||||
|
|
||||||
|
if (previewImage != null)
|
||||||
|
{
|
||||||
|
submarineDisplays[i].submarineImage.Sprite = previewImage;
|
||||||
|
submarineDisplays[i].middleTextBlock.AutoDraw = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
submarineDisplays[i].submarineImage.Sprite = null;
|
||||||
|
submarineDisplays[i].middleTextBlock.Text = missingPreviewText;
|
||||||
|
submarineDisplays[i].middleTextBlock.AutoDraw = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
submarineDisplays[i].selectSubmarineButton.Enabled = true;
|
||||||
|
|
||||||
|
int index = i;
|
||||||
|
submarineDisplays[i].selectSubmarineButton.OnClicked = (button, userData) =>
|
||||||
|
{
|
||||||
|
SelectSubmarine(subToDisplay, submarineDisplays[index].background.Rect);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
submarineDisplays[i].submarineName.Text = subToDisplay.DisplayName;
|
||||||
|
submarineDisplays[i].submarineClass.Text = $"{TextManager.GetWithVariable("submarineclass.classsuffixformat", "[type]", TextManager.Get($"submarineclass.{subToDisplay.SubmarineClass}"))}";
|
||||||
|
|
||||||
|
if (!GameMain.GameSession.IsSubmarineOwned(subToDisplay))
|
||||||
|
{
|
||||||
|
string amountString = currencyShorthandText.Replace("[credits]", subToDisplay.Price.ToString());
|
||||||
|
submarineDisplays[i].submarineFee.Text = priceText.Replace("[amount]", amountString).Replace("[currencyname]", string.Empty).TrimEnd();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (subToDisplay.Name != CurrentOrPendingSubmarine().Name)
|
||||||
|
{
|
||||||
|
if (deliveryFee > 0)
|
||||||
|
{
|
||||||
|
string amountString = currencyShorthandText.Replace("[credits]", deliveryFee.ToString());
|
||||||
|
submarineDisplays[i].submarineFee.Text = deliveryFeeText.Replace("[amount]", amountString).Replace("[currencyname]", string.Empty).TrimEnd();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
submarineDisplays[i].submarineFee.Text = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
submarineDisplays[i].submarineFee.Text = currentSubText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transferService && subToDisplay.Name == CurrentOrPendingSubmarine().Name && updateSubs)
|
||||||
|
{
|
||||||
|
if (selectedSubmarine == null)
|
||||||
|
{
|
||||||
|
CoroutineManager.StartCoroutine(SelectOwnSubmarineWithDelay(subToDisplay, submarineDisplays[i]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SelectSubmarine(subToDisplay, submarineDisplays[i].background.Rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!transferService && selectedSubmarine == null || !transferService && GameMain.GameSession.IsSubmarineOwned(selectedSubmarine) || subToDisplay == selectedSubmarine)
|
||||||
|
{
|
||||||
|
SelectSubmarine(subToDisplay, submarineDisplays[i].background.Rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
submarineIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subsToShow.Count == 0)
|
||||||
|
{
|
||||||
|
SelectSubmarine(null, Rectangle.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateSubmarines()
|
||||||
|
{
|
||||||
|
subsToShow.Clear();
|
||||||
|
if (transferService)
|
||||||
|
{
|
||||||
|
subsToShow.AddRange(GameMain.GameSession.OwnedSubmarines);
|
||||||
|
subsToShow.Sort((x, y) => x.SubmarineClass.CompareTo(y.SubmarineClass));
|
||||||
|
string currentSubName = CurrentOrPendingSubmarine().Name;
|
||||||
|
int currentIndex = subsToShow.FindIndex(s => s.Name == currentSubName);
|
||||||
|
if (currentIndex != -1)
|
||||||
|
{
|
||||||
|
currentPage = (int)Math.Ceiling((currentIndex + 1) / (float)submarinesPerPage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (GameMain.Client == null)
|
||||||
|
{
|
||||||
|
subsToShow.AddRange(SubmarineInfo.SavedSubmarines.Where(s => s.IsCampaignCompatible && !GameMain.GameSession.OwnedSubmarines.Any(os => os.Name == s.Name)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
subsToShow.AddRange(GameMain.NetLobbyScreen.CampaignSubmarines.Where(s => !GameMain.GameSession.OwnedSubmarines.Any(os => os.Name == s.Name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
subsToShow.Sort((x, y) => x.SubmarineClass.CompareTo(y.SubmarineClass));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transferService) SetConfirmButtonState(selectedSubmarine != null && selectedSubmarine.Name != CurrentOrPendingSubmarine().Name);
|
||||||
|
|
||||||
|
subsToShow.Sort((x, y) => x.SubmarineClass.CompareTo(y.SubmarineClass));
|
||||||
|
pageCount = Math.Max(1, (int)Math.Ceiling(subsToShow.Count / (float)submarinesPerPage));
|
||||||
|
UpdatePaging();
|
||||||
|
ContentRefreshRequired = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SubmarineInfo GetSubToDisplay(int index)
|
||||||
|
{
|
||||||
|
if (subsToShow.Count <= index || index < 0) return null;
|
||||||
|
return subsToShow[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
private Sprite GetPreviewImage(SubmarineInfo info)
|
||||||
|
{
|
||||||
|
Sprite preview = info.PreviewImage;
|
||||||
|
|
||||||
|
if (preview == null)
|
||||||
|
{
|
||||||
|
SubmarineInfo potentialMatch;
|
||||||
|
|
||||||
|
if (GameMain.Client == null)
|
||||||
|
{
|
||||||
|
potentialMatch = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.EqualityCheckVal == info.EqualityCheckVal);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
potentialMatch = GameMain.NetLobbyScreen.CampaignSubmarines.FirstOrDefault(s => s.EqualityCheckVal == info.EqualityCheckVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
preview = potentialMatch?.PreviewImage;
|
||||||
|
|
||||||
|
// Try from savedsubmarines with name comparison as a backup
|
||||||
|
if (preview == null)
|
||||||
|
{
|
||||||
|
potentialMatch = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == info.Name);
|
||||||
|
preview = potentialMatch?.PreviewImage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return preview;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initial submarine selection needs a slight wait to allow the layoutgroups to place content properly
|
||||||
|
private IEnumerable<object> SelectOwnSubmarineWithDelay(SubmarineInfo info, SubmarineDisplayContent display)
|
||||||
|
{
|
||||||
|
yield return new WaitForSeconds(0.05f);
|
||||||
|
SelectSubmarine(info, display.background.Rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Selection based on key input
|
||||||
|
private void SelectSubmarine(int index, int direction)
|
||||||
|
{
|
||||||
|
SubmarineInfo nextSub = GetSubToDisplay(index + direction);
|
||||||
|
if (nextSub == null) return;
|
||||||
|
|
||||||
|
for (int i = 0; i < submarineDisplays.Length; i++)
|
||||||
|
{
|
||||||
|
if (submarineDisplays[i].displayedSubmarine == nextSub)
|
||||||
|
{
|
||||||
|
SelectSubmarine(nextSub, submarineDisplays[i].background.Rect);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ChangePage(direction);
|
||||||
|
|
||||||
|
for (int i = 0; i < submarineDisplays.Length; i++)
|
||||||
|
{
|
||||||
|
if (submarineDisplays[i].displayedSubmarine == nextSub)
|
||||||
|
{
|
||||||
|
SelectSubmarine(nextSub, submarineDisplays[i].background.Rect);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SelectSubmarine(SubmarineInfo info, Rectangle backgroundRect)
|
||||||
|
{
|
||||||
|
#if !DEBUG
|
||||||
|
if (selectedSubmarine == info) return;
|
||||||
|
#endif
|
||||||
|
specsFrame.Content.ClearChildren();
|
||||||
|
selectedSubmarine = info;
|
||||||
|
|
||||||
|
if (info != null)
|
||||||
|
{
|
||||||
|
bool owned = GameMain.GameSession.IsSubmarineOwned(info);
|
||||||
|
|
||||||
|
if (owned)
|
||||||
|
{
|
||||||
|
confirmButton.Text = deliveryFee > 0 ? deliveryText : switchText;
|
||||||
|
confirmButton.OnClicked = (button, userData) =>
|
||||||
|
{
|
||||||
|
ShowTransferPrompt();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
confirmButton.Text = purchaseAndSwitchText;
|
||||||
|
confirmButton.OnClicked = (button, userData) =>
|
||||||
|
{
|
||||||
|
ShowBuyPrompt(false);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
confirmButtonAlt.Text = purchaseOnlyText;
|
||||||
|
confirmButtonAlt.OnClicked = (button, userData) =>
|
||||||
|
{
|
||||||
|
ShowBuyPrompt(true);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
SetConfirmButtonState(selectedSubmarine.Name != CurrentOrPendingSubmarine().Name);
|
||||||
|
|
||||||
|
selectedSubmarineIndicator.RectTransform.NonScaledSize = backgroundRect.Size;
|
||||||
|
selectedSubmarineIndicator.RectTransform.AbsoluteOffset = new Point(backgroundRect.Left - submarineHorizontalGroup.Rect.Left, 0);
|
||||||
|
|
||||||
|
Sprite previewImage = GetPreviewImage(info);
|
||||||
|
listBackground.Sprite = previewImage;
|
||||||
|
listBackground.SetCrop(true);
|
||||||
|
|
||||||
|
ScalableFont font = GUI.Font;
|
||||||
|
info.CreateSpecsWindow(specsFrame, font);
|
||||||
|
descriptionTextBlock.Text = info.Description;
|
||||||
|
descriptionTextBlock.CalculateHeightFromText();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
listBackground.Sprite = null;
|
||||||
|
listBackground.SetCrop(false);
|
||||||
|
descriptionTextBlock.Text = string.Empty;
|
||||||
|
selectedSubmarineIndicator.RectTransform.NonScaledSize = Point.Zero;
|
||||||
|
SetConfirmButtonState(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetConfirmButtonState(bool state)
|
||||||
|
{
|
||||||
|
if (confirmButtonAlt != null)
|
||||||
|
{
|
||||||
|
confirmButtonAlt.Enabled = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (confirmButton != null)
|
||||||
|
{
|
||||||
|
confirmButton.Enabled = state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SubmarineInfo CurrentOrPendingSubmarine()
|
||||||
|
{
|
||||||
|
if (GameMain.GameSession?.Campaign?.PendingSubmarineSwitch == null)
|
||||||
|
{
|
||||||
|
return Submarine.MainSub.Info;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return GameMain.GameSession.Campaign.PendingSubmarineSwitch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ChangePage(int pageChangeDirection)
|
||||||
|
{
|
||||||
|
SelectSubmarine(null, Rectangle.Empty);
|
||||||
|
if (pageChangeDirection < 0 && currentPage > 1) currentPage--;
|
||||||
|
if (pageChangeDirection > 0 && currentPage < pageCount) currentPage++;
|
||||||
|
browseLeftButton.Enabled = currentPage > 1;
|
||||||
|
browseRightButton.Enabled = currentPage < pageCount;
|
||||||
|
|
||||||
|
RefreshSubmarineDisplay(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShowTransferPrompt()
|
||||||
|
{
|
||||||
|
if (GameMain.GameSession.Campaign.Money < deliveryFee && deliveryFee > 0)
|
||||||
|
{
|
||||||
|
new GUIMessageBox(TextManager.Get("deliveryrequestheader"), TextManager.GetWithVariables("notenoughmoneyfordeliverytext", notEnoughCreditsDeliveryTextVariables,
|
||||||
|
new string[] { currencyLongText, selectedSubmarine.DisplayName, deliveryLocationName, GameMain.GameSession.Map.CurrentLocation.Name }));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GUIMessageBox msgBox;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msgBox = new GUIMessageBox(TextManager.Get("switchsubmarineheader"), TextManager.GetWithVariables("switchsubmarinetext", SwitchTextVariables,
|
||||||
|
new string[2] { CurrentOrPendingSubmarine().DisplayName, selectedSubmarine.DisplayName }), messageBoxOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
msgBox.Buttons[0].OnClicked = (applyButton, obj) =>
|
||||||
|
{
|
||||||
|
if (GameMain.Client == null)
|
||||||
|
{
|
||||||
|
GameMain.GameSession.SwitchSubmarine(selectedSubmarine, deliveryFee);
|
||||||
|
GameMain.GameSession.Campaign.UpgradeManager.RefundResetAndReload(selectedSubmarine);
|
||||||
|
RefreshSubmarineDisplay(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GameMain.Client.InitiateSubmarineChange(selectedSubmarine, Networking.VoteType.SwitchSub);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
||||||
|
msgBox.Buttons[1].OnClicked = msgBox.Close;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShowBuyPrompt(bool purchaseOnly)
|
||||||
|
{
|
||||||
|
if (GameMain.GameSession.Campaign.Money < selectedSubmarine.Price)
|
||||||
|
{
|
||||||
|
new GUIMessageBox(TextManager.Get("purchasesubmarineheader"), TextManager.GetWithVariables("notenoughmoneyforpurchasetext", notEnoughCreditsPurchaseTextVariables,
|
||||||
|
new string[2] { currencyLongText, selectedSubmarine.DisplayName }));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GUIMessageBox msgBox;
|
||||||
|
|
||||||
|
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.Buttons[0].OnClicked = (applyButton, obj) =>
|
||||||
|
{
|
||||||
|
if (GameMain.Client == null)
|
||||||
|
{
|
||||||
|
GameMain.GameSession.PurchaseSubmarine(selectedSubmarine);
|
||||||
|
GameMain.GameSession.SwitchSubmarine(selectedSubmarine, 0);
|
||||||
|
GameMain.GameSession.Campaign.UpgradeManager.RefundResetAndReload(selectedSubmarine);
|
||||||
|
RefreshSubmarineDisplay(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GameMain.Client.InitiateSubmarineChange(selectedSubmarine, Networking.VoteType.PurchaseAndSwitchSub);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msgBox = new GUIMessageBox(TextManager.Get("purchasesubmarineheader"), TextManager.GetWithVariables("purchasesubmarinetext", PurchaseTextVariables,
|
||||||
|
new string[3] { selectedSubmarine.DisplayName, selectedSubmarine.Price.ToString(), currencyLongText }), messageBoxOptions);
|
||||||
|
|
||||||
|
msgBox.Buttons[0].OnClicked = (applyButton, obj) =>
|
||||||
|
{
|
||||||
|
if (GameMain.Client == null)
|
||||||
|
{
|
||||||
|
GameMain.GameSession.PurchaseSubmarine(selectedSubmarine);
|
||||||
|
RefreshSubmarineDisplay(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GameMain.Client.InitiateSubmarineChange(selectedSubmarine, Networking.VoteType.PurchaseSub);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
||||||
|
msgBox.Buttons[1].OnClicked = msgBox.Close;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ using Microsoft.Xna.Framework;
|
|||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Barotrauma.Networking;
|
using Barotrauma.Networking;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -13,7 +14,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private static bool initialized = false;
|
private static bool initialized = false;
|
||||||
|
|
||||||
private static UISprite spectateIcon, deadIcon, disconnectedIcon;
|
private static UISprite spectateIcon, disconnectedIcon;
|
||||||
private static Sprite ownerIcon, moderatorIcon;
|
private static Sprite ownerIcon, moderatorIcon;
|
||||||
|
|
||||||
private enum InfoFrameTab { Crew, Mission, MyCharacter, Traitor };
|
private enum InfoFrameTab { Crew, Mission, MyCharacter, Traitor };
|
||||||
@@ -31,7 +32,7 @@ namespace Barotrauma
|
|||||||
private List<Character.TeamType> teamIDs;
|
private List<Character.TeamType> teamIDs;
|
||||||
private const string inLobbyString = "\u2022 \u2022 \u2022";
|
private const string inLobbyString = "\u2022 \u2022 \u2022";
|
||||||
|
|
||||||
private static Color ownCharacterBGColor = Color.Gold * 0.7f;
|
public static Color OwnCharacterBGColor = Color.Gold * 0.7f;
|
||||||
|
|
||||||
private class LinkedGUI
|
private class LinkedGUI
|
||||||
{
|
{
|
||||||
@@ -115,10 +116,9 @@ namespace Barotrauma
|
|||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
spectateIcon = GUI.Style.GetComponentStyle("SpectateIcon").Sprites[GUIComponent.ComponentState.None][0];
|
spectateIcon = GUI.Style.GetComponentStyle("SpectateIcon").Sprites[GUIComponent.ComponentState.None][0];
|
||||||
deadIcon = GUI.Style.GetComponentStyle("DeadIcon").Sprites[GUIComponent.ComponentState.None][0];
|
|
||||||
disconnectedIcon = GUI.Style.GetComponentStyle("DisconnectedIcon").Sprites[GUIComponent.ComponentState.None][0];
|
disconnectedIcon = GUI.Style.GetComponentStyle("DisconnectedIcon").Sprites[GUIComponent.ComponentState.None][0];
|
||||||
ownerIcon = GUI.Style.GetComponentStyle("OwnerIcon").Sprites[GUIComponent.ComponentState.None][0].Sprite;
|
ownerIcon = GUI.Style.GetComponentStyle("OwnerIcon").GetDefaultSprite();
|
||||||
moderatorIcon = GUI.Style.GetComponentStyle("ModeratorIcon").Sprites[GUIComponent.ComponentState.None][0].Sprite;
|
moderatorIcon = GUI.Style.GetComponentStyle("ModeratorIcon").GetDefaultSprite();
|
||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,7 +279,7 @@ namespace Barotrauma
|
|||||||
teamIDs = crew.Select(c => c.TeamID).Distinct().ToList();
|
teamIDs = crew.Select(c => c.TeamID).Distinct().ToList();
|
||||||
|
|
||||||
// Show own team first when there's more than one team
|
// Show own team first when there's more than one team
|
||||||
if (teamIDs.Count > 1 && GameMain.Client.Character != null)
|
if (teamIDs.Count > 1 && GameMain.Client?.Character != null)
|
||||||
{
|
{
|
||||||
Character.TeamType ownTeam = GameMain.Client.Character.TeamID;
|
Character.TeamType ownTeam = GameMain.Client.Character.TeamID;
|
||||||
teamIDs = teamIDs.OrderBy(i => i != ownTeam).ThenBy(i => i).ToList();
|
teamIDs = teamIDs.OrderBy(i => i != ownTeam).ThenBy(i => i).ToList();
|
||||||
@@ -408,7 +408,7 @@ namespace Barotrauma
|
|||||||
GUIFrame frame = new GUIFrame(new RectTransform(new Point(crewListArray[i].Content.Rect.Width, GUI.IntScale(33f)), crewListArray[i].Content.RectTransform), style: "ListBoxElement")
|
GUIFrame frame = new GUIFrame(new RectTransform(new Point(crewListArray[i].Content.Rect.Width, GUI.IntScale(33f)), crewListArray[i].Content.RectTransform), style: "ListBoxElement")
|
||||||
{
|
{
|
||||||
UserData = character,
|
UserData = character,
|
||||||
Color = (Character.Controlled == character) ? ownCharacterBGColor : Color.Transparent
|
Color = (Character.Controlled == character) ? OwnCharacterBGColor : Color.Transparent
|
||||||
};
|
};
|
||||||
|
|
||||||
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.9f), frame.RectTransform, Anchor.Center), isHorizontal: true)
|
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.9f), frame.RectTransform, Anchor.Center), isHorizontal: true)
|
||||||
@@ -486,7 +486,7 @@ namespace Barotrauma
|
|||||||
GUIFrame frame = new GUIFrame(new RectTransform(new Point(crewListArray[i].Content.Rect.Width, GUI.IntScale(33f)), crewListArray[i].Content.RectTransform), style: "ListBoxElement")
|
GUIFrame frame = new GUIFrame(new RectTransform(new Point(crewListArray[i].Content.Rect.Width, GUI.IntScale(33f)), crewListArray[i].Content.RectTransform), style: "ListBoxElement")
|
||||||
{
|
{
|
||||||
UserData = character,
|
UserData = character,
|
||||||
Color = (GameMain.NetworkMember != null && GameMain.Client.Character == character) ? ownCharacterBGColor : Color.Transparent
|
Color = (GameMain.NetworkMember != null && GameMain.Client.Character == character) ? OwnCharacterBGColor : Color.Transparent
|
||||||
};
|
};
|
||||||
|
|
||||||
frame.OnSecondaryClicked += (component, data) =>
|
frame.OnSecondaryClicked += (component, data) =>
|
||||||
@@ -631,7 +631,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (GameMain.NetworkMember == null || client == null || !client.HasPermissions) return null;
|
if (GameMain.NetworkMember == null || client == null || !client.HasPermissions) return null;
|
||||||
|
|
||||||
if (!client.AllowKicking) // Owner cannot be kicked
|
if (client.IsOwner) // Owner cannot be kicked
|
||||||
{
|
{
|
||||||
return ownerIcon;
|
return ownerIcon;
|
||||||
}
|
}
|
||||||
@@ -649,7 +649,10 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else if (client.Character != null && client.Character.IsDead)
|
else if (client.Character != null && client.Character.IsDead)
|
||||||
{
|
{
|
||||||
client.Character.Info.DrawJobIcon(spriteBatch, area);
|
if (client.Character.Info != null)
|
||||||
|
{
|
||||||
|
client.Character.Info.DrawJobIcon(spriteBatch, area);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -780,7 +783,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public static void StorePlayerConnectionChangeMessage(ChatMessage message)
|
public static void StorePlayerConnectionChangeMessage(ChatMessage message)
|
||||||
{
|
{
|
||||||
if (!GameMain.GameSession?.GameMode?.IsRunning ?? true) { return; }
|
if (!GameMain.GameSession?.IsRunning ?? true) { return; }
|
||||||
|
|
||||||
string msg = ChatMessage.GetTimeStamp() + message.TextWithSender;
|
string msg = ChatMessage.GetTimeStamp() + message.TextWithSender;
|
||||||
storedMessages.Add(new Pair<string, PlayerConnectionChangeType>(msg, message.ChangeType));
|
storedMessages.Add(new Pair<string, PlayerConnectionChangeType>(msg, message.ChangeType));
|
||||||
@@ -847,15 +850,15 @@ namespace Barotrauma
|
|||||||
infoFrame.ClearChildren();
|
infoFrame.ClearChildren();
|
||||||
GUIFrame missionFrame = new GUIFrame(new RectTransform(Vector2.One, infoFrame.RectTransform, Anchor.TopCenter), style: "GUIFrameListBox");
|
GUIFrame missionFrame = new GUIFrame(new RectTransform(Vector2.One, infoFrame.RectTransform, Anchor.TopCenter), style: "GUIFrameListBox");
|
||||||
int padding = (int)(0.0245f * missionFrame.Rect.Height);
|
int padding = (int)(0.0245f * missionFrame.Rect.Height);
|
||||||
Location endLocation = GameMain.GameSession.EndLocation;
|
Location location = GameMain.GameSession.EndLocation != null ? GameMain.GameSession.EndLocation : GameMain.GameSession.StartLocation;
|
||||||
Sprite portrait = endLocation.Type.GetPortrait(endLocation.PortraitId);
|
Sprite portrait = location.Type.GetPortrait(location.PortraitId);
|
||||||
bool hasPortrait = portrait != null && portrait.SourceRect.Width > 0 && portrait.SourceRect.Height > 0;
|
bool hasPortrait = portrait != null && portrait.SourceRect.Width > 0 && portrait.SourceRect.Height > 0;
|
||||||
int contentWidth = hasPortrait ? (int)(missionFrame.Rect.Width * 0.951f) : missionFrame.Rect.Width - padding * 2;
|
int contentWidth = hasPortrait ? (int)(missionFrame.Rect.Width * 0.951f) : missionFrame.Rect.Width - padding * 2;
|
||||||
|
|
||||||
Vector2 locationNameSize = GUI.LargeFont.MeasureString(endLocation.Name);
|
Vector2 locationNameSize = GUI.LargeFont.MeasureString(location.Name);
|
||||||
Vector2 locationTypeSize = GUI.SubHeadingFont.MeasureString(endLocation.Name);
|
Vector2 locationTypeSize = GUI.SubHeadingFont.MeasureString(location.Name);
|
||||||
GUITextBlock locationNameText = new GUITextBlock(new RectTransform(new Point(contentWidth, (int)locationNameSize.Y), missionFrame.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, padding) }, endLocation.Name, font: GUI.LargeFont);
|
GUITextBlock locationNameText = new GUITextBlock(new RectTransform(new Point(contentWidth, (int)locationNameSize.Y), missionFrame.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, padding) }, location.Name, font: GUI.LargeFont);
|
||||||
GUITextBlock locationTypeText = new GUITextBlock(new RectTransform(new Point(contentWidth, (int)locationTypeSize.Y), missionFrame.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, locationNameText.Rect.Height + padding) }, endLocation.Type.Name, font: GUI.SubHeadingFont);
|
GUITextBlock locationTypeText = new GUITextBlock(new RectTransform(new Point(contentWidth, (int)locationTypeSize.Y), missionFrame.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, locationNameText.Rect.Height + padding) }, location.Type.Name, font: GUI.SubHeadingFont);
|
||||||
|
|
||||||
int locationInfoYOffset = locationNameText.Rect.Height + locationTypeText.Rect.Height + padding * 2;
|
int locationInfoYOffset = locationNameText.Rect.Height + locationTypeText.Rect.Height + padding * 2;
|
||||||
|
|
||||||
@@ -881,7 +884,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
string missionNameString = ToolBox.WrapText(mission.Name, missionTextGroup.Rect.Width, GUI.LargeFont);
|
string missionNameString = ToolBox.WrapText(mission.Name, missionTextGroup.Rect.Width, GUI.LargeFont);
|
||||||
string missionDescriptionString = ToolBox.WrapText(mission.Description, missionTextGroup.Rect.Width, GUI.Font);
|
string missionDescriptionString = ToolBox.WrapText(mission.Description, missionTextGroup.Rect.Width, GUI.Font);
|
||||||
string missionRewardString = ToolBox.WrapText(TextManager.GetWithVariable("MissionReward", "[reward]", mission.Reward.ToString()), missionTextGroup.Rect.Width, GUI.Font);
|
string rewardText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", mission.Reward));
|
||||||
|
string missionRewardString = ToolBox.WrapText(TextManager.GetWithVariable("MissionReward", "[reward]", rewardText), missionTextGroup.Rect.Width, GUI.Font);
|
||||||
|
|
||||||
Vector2 missionNameSize = GUI.LargeFont.MeasureString(missionNameString);
|
Vector2 missionNameSize = GUI.LargeFont.MeasureString(missionNameString);
|
||||||
Vector2 missionDescriptionSize = GUI.Font.MeasureString(missionDescriptionString);
|
Vector2 missionDescriptionSize = GUI.Font.MeasureString(missionDescriptionString);
|
||||||
@@ -890,13 +894,15 @@ namespace Barotrauma
|
|||||||
missionDescriptionHolder.RectTransform.NonScaledSize = new Point(missionDescriptionHolder.RectTransform.NonScaledSize.X, (int)(missionNameSize.Y + missionDescriptionSize.Y + missionRewardSize.Y));
|
missionDescriptionHolder.RectTransform.NonScaledSize = new Point(missionDescriptionHolder.RectTransform.NonScaledSize.X, (int)(missionNameSize.Y + missionDescriptionSize.Y + missionRewardSize.Y));
|
||||||
missionTextGroup.RectTransform.NonScaledSize = new Point(missionTextGroup.RectTransform.NonScaledSize.X, missionDescriptionHolder.RectTransform.NonScaledSize.Y);
|
missionTextGroup.RectTransform.NonScaledSize = new Point(missionTextGroup.RectTransform.NonScaledSize.X, missionDescriptionHolder.RectTransform.NonScaledSize.Y);
|
||||||
|
|
||||||
float iconAspectRatio = mission.Prefab.Icon.SourceRect.Width / mission.Prefab.Icon.SourceRect.Height;
|
if (mission.Prefab.Icon != null)
|
||||||
int iconWidth = (int)(0.225f * missionDescriptionHolder.RectTransform.NonScaledSize.X);
|
{
|
||||||
int iconHeight = Math.Max(missionTextGroup.RectTransform.NonScaledSize.Y, (int)(iconWidth * iconAspectRatio));
|
float iconAspectRatio = mission.Prefab.Icon.SourceRect.Width / mission.Prefab.Icon.SourceRect.Height;
|
||||||
Point iconSize = new Point(iconWidth, iconHeight);
|
int iconWidth = (int)(0.225f * missionDescriptionHolder.RectTransform.NonScaledSize.X);
|
||||||
|
int iconHeight = Math.Max(missionTextGroup.RectTransform.NonScaledSize.Y, (int)(iconWidth * iconAspectRatio));
|
||||||
new GUIImage(new RectTransform(iconSize, missionDescriptionHolder.RectTransform), mission.Prefab.Icon, null, true) { Color = mission.Prefab.IconColor };
|
Point iconSize = new Point(iconWidth, iconHeight);
|
||||||
|
|
||||||
|
new GUIImage(new RectTransform(iconSize, missionDescriptionHolder.RectTransform), mission.Prefab.Icon, null, true) { Color = mission.Prefab.IconColor };
|
||||||
|
}
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionNameString, font: GUI.LargeFont);
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionNameString, font: GUI.LargeFont);
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionRewardString);
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionRewardString);
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionDescriptionString);
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionDescriptionString);
|
||||||
|
|||||||
@@ -37,6 +37,12 @@ namespace Barotrauma
|
|||||||
private set;
|
private set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool MaintainBorderAspectRatio
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// How much the borders of a sliced sprite are allowed to scale
|
/// How much the borders of a sliced sprite are allowed to scale
|
||||||
/// You may for example want to prevent a 1-pixel border from scaling down (and disappearing) on small resolutions
|
/// You may for example want to prevent a 1-pixel border from scaling down (and disappearing) on small resolutions
|
||||||
@@ -52,6 +58,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Sprite = new Sprite(element);
|
Sprite = new Sprite(element);
|
||||||
MaintainAspectRatio = element.GetAttributeBool("maintainaspectratio", false);
|
MaintainAspectRatio = element.GetAttributeBool("maintainaspectratio", false);
|
||||||
|
MaintainBorderAspectRatio = element.GetAttributeBool("maintainborderaspectratio", false);
|
||||||
Tile = element.GetAttributeBool("tile", true);
|
Tile = element.GetAttributeBool("tile", true);
|
||||||
CrossFadeIn = element.GetAttributeBool("crossfadein", CrossFadeIn);
|
CrossFadeIn = element.GetAttributeBool("crossfadein", CrossFadeIn);
|
||||||
CrossFadeOut = element.GetAttributeBool("crossfadeout", CrossFadeOut);
|
CrossFadeOut = element.GetAttributeBool("crossfadeout", CrossFadeOut);
|
||||||
@@ -120,13 +127,16 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Vector2 pos = new Vector2(rect.X, rect.Y);
|
Vector2 pos = new Vector2(rect.X, rect.Y);
|
||||||
|
|
||||||
float scale = GetSliceBorderScale(rect.Size);
|
float scale = MaintainBorderAspectRatio ? 1.0f : GetSliceBorderScale(rect.Size);
|
||||||
|
float aspectScale = MaintainBorderAspectRatio ? Math.Min((float)rect.Width / Sprite.SourceRect.Width, (float)rect.Height / Sprite.SourceRect.Height) : 1.0f;
|
||||||
|
|
||||||
int centerHeight = rect.Height - (int)((Slices[0].Height + Slices[6].Height) * scale);
|
int centerHeight = rect.Height - (int)((Slices[0].Height + Slices[6].Height) * scale);
|
||||||
int centerWidth = rect.Width - (int)((Slices[0].Width + Slices[2].Width) * scale);
|
int centerWidth = rect.Width - (int)((Slices[0].Width + Slices[2].Width) * scale * aspectScale);
|
||||||
|
|
||||||
for (int x = 0; x < 3; x++)
|
for (int x = 0; x < 3; x++)
|
||||||
{
|
{
|
||||||
int width = (int)(x == 1 ? centerWidth : Slices[x].Width * scale);
|
|
||||||
|
int width = (int)(x == 1 ? centerWidth : Slices[x].Width * scale * aspectScale);
|
||||||
if (width <= 0) { continue; }
|
if (width <= 0) { continue; }
|
||||||
for (int y = 0; y < 3; y++)
|
for (int y = 0; y < 3; y++)
|
||||||
{
|
{
|
||||||
@@ -147,7 +157,7 @@ namespace Barotrauma
|
|||||||
else if (Tile)
|
else if (Tile)
|
||||||
{
|
{
|
||||||
Vector2 startPos = new Vector2(rect.X, rect.Y);
|
Vector2 startPos = new Vector2(rect.X, rect.Y);
|
||||||
Sprite.DrawTiled(spriteBatch, startPos, new Vector2(rect.Width, rect.Height), null, color);
|
Sprite.DrawTiled(spriteBatch, startPos, new Vector2(rect.Width, rect.Height), color);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,235 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Barotrauma.Networking;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
class VotingInterface
|
||||||
|
{
|
||||||
|
public bool VoteRunning = false;
|
||||||
|
|
||||||
|
private GUIFrame frame;
|
||||||
|
private GUITextBlock votingTextBlock, votedTextBlock, voteCounter;
|
||||||
|
private GUIProgressBar votingTimer;
|
||||||
|
private GUIButton yesVoteButton, noVoteButton;
|
||||||
|
private Action onVoteEnd;
|
||||||
|
|
||||||
|
private int yesVotes, noVotes, maxVotes;
|
||||||
|
private Func<int> getYesVotes, getNoVotes, getMaxVotes;
|
||||||
|
private bool votePassed;
|
||||||
|
|
||||||
|
private string votingOnText;
|
||||||
|
private List<RichTextData> votingOnTextData;
|
||||||
|
private float votingTime = 100f;
|
||||||
|
private float timer;
|
||||||
|
private VoteType currentVoteType;
|
||||||
|
private Color submarineColor => GUI.Style.Orange;
|
||||||
|
private Point createdForResolution;
|
||||||
|
|
||||||
|
public VotingInterface(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);
|
||||||
|
|
||||||
|
Initialize(starter, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Initialize(Client starter, VoteType type)
|
||||||
|
{
|
||||||
|
currentVoteType = type;
|
||||||
|
CreateVotingGUI();
|
||||||
|
if (starter.ID == GameMain.Client.ID) SetGUIToVotedState(2);
|
||||||
|
VoteRunning = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateVotingGUI()
|
||||||
|
{
|
||||||
|
createdForResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||||
|
|
||||||
|
if (frame != null) frame.Parent.RemoveChild(frame);
|
||||||
|
frame = new GUIFrame(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.VotingArea, GameMain.Client.InGameHUD.RectTransform), style: "");
|
||||||
|
|
||||||
|
int padding = HUDLayoutSettings.Padding * 2;
|
||||||
|
int spacing = HUDLayoutSettings.Padding;
|
||||||
|
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.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.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);
|
||||||
|
|
||||||
|
yOffset += voteCounter.Rect.Height + spacing;
|
||||||
|
|
||||||
|
votingTimer = new GUIProgressBar(new RectTransform(new Point(paddedWidth, Math.Max(spacing, 8)), frame.RectTransform) { AbsoluteOffset = new Point(padding, yOffset) }, HUDLayoutSettings.Padding);
|
||||||
|
votingTimer.RectTransform.IsFixedSize = true;
|
||||||
|
yOffset += votingTimer.Rect.Height + spacing;
|
||||||
|
|
||||||
|
int buttonWidth = (int)(paddedWidth * 0.3f);
|
||||||
|
yesVoteButton = new GUIButton(new RectTransform(new Point(buttonWidth, 0), frame.RectTransform) { AbsoluteOffset = new Point((int)(frame.Rect.Width / 2f - buttonWidth - spacing), yOffset) }, TextManager.Get("yes"))
|
||||||
|
{
|
||||||
|
OnClicked = (applyButton, obj) =>
|
||||||
|
{
|
||||||
|
SetGUIToVotedState(2);
|
||||||
|
GameMain.Client.Vote(currentVoteType, 2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
noVoteButton = new GUIButton(new RectTransform(new Point(buttonWidth, 0), frame.RectTransform) { AbsoluteOffset = new Point(yesVoteButton.RectTransform.AbsoluteOffset.X + yesVoteButton.Rect.Width + padding, yOffset) }, TextManager.Get("no"))
|
||||||
|
{
|
||||||
|
OnClicked = (applyButton, obj) =>
|
||||||
|
{
|
||||||
|
SetGUIToVotedState(1);
|
||||||
|
GameMain.Client.Vote(currentVoteType, 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
votedTextBlock = new GUITextBlock(new RectTransform(new Point(paddedWidth, yesVoteButton.Rect.Height), frame.RectTransform), string.Empty, textAlignment: Alignment.Center);
|
||||||
|
votedTextBlock.RectTransform.IsFixedSize = true;
|
||||||
|
votedTextBlock.RectTransform.AbsoluteOffset = new Point(padding, yOffset);
|
||||||
|
votedTextBlock.Visible = false;
|
||||||
|
|
||||||
|
yOffset += yesVoteButton.Rect.Height;
|
||||||
|
|
||||||
|
frame.RectTransform.NonScaledSize = new Point(frame.Rect.Width, yOffset + padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetGUIToVotedState(int vote)
|
||||||
|
{
|
||||||
|
yesVoteButton.Visible = noVoteButton.Visible = false;
|
||||||
|
votedTextBlock.Text = TextManager.Get(vote == 2 ? "yesvoted" : "novoted");
|
||||||
|
votedTextBlock.Visible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(float deltaTime)
|
||||||
|
{
|
||||||
|
if (!VoteRunning) return;
|
||||||
|
if (GameMain.GraphicsWidth != createdForResolution.X || GameMain.GraphicsHeight != createdForResolution.Y) CreateVotingGUI();
|
||||||
|
yesVotes = getYesVotes();
|
||||||
|
noVotes = getNoVotes();
|
||||||
|
maxVotes = getMaxVotes();
|
||||||
|
voteCounter.Text = $"({yesVotes + noVotes}/{maxVotes})";
|
||||||
|
timer += deltaTime;
|
||||||
|
votingTimer.BarSize = timer / votingTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void EndVote(bool passed, int yesVoteFinal, int noVoteFinal)
|
||||||
|
{
|
||||||
|
VoteRunning = false;
|
||||||
|
votePassed = passed;
|
||||||
|
yesVotes = yesVoteFinal;
|
||||||
|
noVotes = noVoteFinal;
|
||||||
|
onVoteEnd?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Submarine Voting
|
||||||
|
private void SetSubmarineVotingText(Client starter, SubmarineInfo info, VoteType type)
|
||||||
|
{
|
||||||
|
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‖";
|
||||||
|
string submarineRichString = $"‖color:{submarineColor.R},{submarineColor.G},{submarineColor.B}‖{info.DisplayName}‖color:end‖";
|
||||||
|
|
||||||
|
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() });
|
||||||
|
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() });
|
||||||
|
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() });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
votingOnText = TextManager.GetWithVariables("submarineswitchnofeevote", new string[] { "[playername]", "[submarinename]" }, new string[] { characterRichString, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SendSubmarineVoteEndMessage(SubmarineInfo info, VoteType type)
|
||||||
|
{
|
||||||
|
GameMain.NetworkMember.AddChatMessage(GetSubmarineVoteResultMessage(info, type, yesVotes.ToString(), noVotes.ToString(), votePassed), ChatMessageType.Server);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetSubmarineVoteResultMessage(SubmarineInfo info, VoteType type, string yesVoteString, string noVoteString, bool votePassed)
|
||||||
|
{
|
||||||
|
string 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 });
|
||||||
|
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 });
|
||||||
|
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 });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = TextManager.GetWithVariables(votePassed ? "submarineswitchnofeevotepassed" : "submarineswitchnofeevotefailed", new string[] { "[submarinename]", "[yesvotecount]", "[novotecount]" }, new string[] { info.DisplayName, yesVoteString, noVoteString });
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public void Remove()
|
||||||
|
{
|
||||||
|
if (frame != null)
|
||||||
|
{
|
||||||
|
frame.Parent.RemoveChild(frame);
|
||||||
|
frame = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,6 +17,7 @@ using System.Threading;
|
|||||||
using Barotrauma.Tutorials;
|
using Barotrauma.Tutorials;
|
||||||
using Barotrauma.Media;
|
using Barotrauma.Media;
|
||||||
using Barotrauma.Extensions;
|
using Barotrauma.Extensions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -35,7 +36,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public static GameScreen GameScreen;
|
public static GameScreen GameScreen;
|
||||||
public static MainMenuScreen MainMenuScreen;
|
public static MainMenuScreen MainMenuScreen;
|
||||||
public static LobbyScreen LobbyScreen;
|
|
||||||
|
|
||||||
public static NetLobbyScreen NetLobbyScreen;
|
public static NetLobbyScreen NetLobbyScreen;
|
||||||
public static ServerListScreen ServerListScreen;
|
public static ServerListScreen ServerListScreen;
|
||||||
@@ -45,8 +45,11 @@ namespace Barotrauma
|
|||||||
public static ParticleEditorScreen ParticleEditorScreen;
|
public static ParticleEditorScreen ParticleEditorScreen;
|
||||||
public static LevelEditorScreen LevelEditorScreen;
|
public static LevelEditorScreen LevelEditorScreen;
|
||||||
public static SpriteEditorScreen SpriteEditorScreen;
|
public static SpriteEditorScreen SpriteEditorScreen;
|
||||||
|
public static EventEditorScreen EventEditorScreen;
|
||||||
public static CharacterEditor.CharacterEditorScreen CharacterEditorScreen;
|
public static CharacterEditor.CharacterEditorScreen CharacterEditorScreen;
|
||||||
|
|
||||||
|
public static CampaignEndScreen CampaignEndScreen;
|
||||||
|
|
||||||
public static Lights.LightManager LightManager;
|
public static Lights.LightManager LightManager;
|
||||||
|
|
||||||
public static Sounds.SoundManager SoundManager;
|
public static Sounds.SoundManager SoundManager;
|
||||||
@@ -79,6 +82,10 @@ namespace Barotrauma
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (gameSession == value) { return; }
|
if (gameSession == value) { return; }
|
||||||
|
if (value == null && Screen.Selected == GameScreen && gameSession.GameMode is CampaignMode)
|
||||||
|
{
|
||||||
|
DebugConsole.AddWarning("GameSession set to null while in the game screen\n" + Environment.StackTrace);
|
||||||
|
}
|
||||||
if (gameSession?.GameMode != null && gameSession.GameMode != value?.GameMode)
|
if (gameSession?.GameMode != null && gameSession.GameMode != value?.GameMode)
|
||||||
{
|
{
|
||||||
gameSession.GameMode.Remove();
|
gameSession.GameMode.Remove();
|
||||||
@@ -100,7 +107,7 @@ namespace Barotrauma
|
|||||||
private CoroutineHandle loadingCoroutine;
|
private CoroutineHandle loadingCoroutine;
|
||||||
private bool hasLoaded;
|
private bool hasLoaded;
|
||||||
|
|
||||||
private GameTime fixedTime;
|
private readonly GameTime fixedTime;
|
||||||
|
|
||||||
public string ConnectName;
|
public string ConnectName;
|
||||||
public string ConnectEndpoint;
|
public string ConnectEndpoint;
|
||||||
@@ -110,7 +117,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private Viewport defaultViewport;
|
private Viewport defaultViewport;
|
||||||
|
|
||||||
public event Action OnResolutionChanged;
|
public event Action ResolutionChanged;
|
||||||
|
|
||||||
private bool exiting;
|
private bool exiting;
|
||||||
|
|
||||||
@@ -190,7 +197,6 @@ namespace Barotrauma
|
|||||||
public GameMain(string[] args)
|
public GameMain(string[] args)
|
||||||
{
|
{
|
||||||
Content.RootDirectory = "Content";
|
Content.RootDirectory = "Content";
|
||||||
|
|
||||||
#if DEBUG && WINDOWS
|
#if DEBUG && WINDOWS
|
||||||
GraphicsAdapter.UseDebugLayers = true;
|
GraphicsAdapter.UseDebugLayers = true;
|
||||||
#endif
|
#endif
|
||||||
@@ -273,7 +279,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
defaultViewport = GraphicsDevice.Viewport;
|
defaultViewport = GraphicsDevice.Viewport;
|
||||||
|
|
||||||
OnResolutionChanged?.Invoke();
|
ResolutionChanged?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetWindowMode(WindowMode windowMode)
|
public void SetWindowMode(WindowMode windowMode)
|
||||||
@@ -455,9 +461,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
bool waitingForWorkshopUpdates = true;
|
bool waitingForWorkshopUpdates = true;
|
||||||
bool result = false;
|
bool result = false;
|
||||||
TaskPool.Add(SteamManager.AutoUpdateWorkshopItemsAsync(), (task) =>
|
TaskPool.Add("AutoUpdateWorkshopItemsAsync",
|
||||||
|
SteamManager.AutoUpdateWorkshopItemsAsync(), (task) =>
|
||||||
{
|
{
|
||||||
result = task.Result;
|
result = ((Task<bool>)task).Result;
|
||||||
waitingForWorkshopUpdates = false;
|
waitingForWorkshopUpdates = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -521,6 +528,10 @@ namespace Barotrauma
|
|||||||
|
|
||||||
yield return CoroutineStatus.Running;
|
yield return CoroutineStatus.Running;
|
||||||
|
|
||||||
|
TaskPool.Add("InitRelayNetworkAccess", SteamManager.InitRelayNetworkAccess(), (t) => { });
|
||||||
|
|
||||||
|
FactionPrefab.LoadFactions();
|
||||||
|
NPCSet.LoadSets();
|
||||||
CharacterPrefab.LoadAll();
|
CharacterPrefab.LoadAll();
|
||||||
MissionPrefab.Init();
|
MissionPrefab.Init();
|
||||||
TraitorMissionPrefab.Init();
|
TraitorMissionPrefab.Init();
|
||||||
@@ -528,8 +539,9 @@ namespace Barotrauma
|
|||||||
Tutorials.Tutorial.Init();
|
Tutorials.Tutorial.Init();
|
||||||
MapGenerationParams.Init();
|
MapGenerationParams.Init();
|
||||||
LevelGenerationParams.LoadPresets();
|
LevelGenerationParams.LoadPresets();
|
||||||
|
OutpostGenerationParams.LoadPresets();
|
||||||
WreckAIConfig.LoadAll();
|
WreckAIConfig.LoadAll();
|
||||||
ScriptedEventSet.LoadPrefabs();
|
EventSet.LoadPrefabs();
|
||||||
AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions));
|
AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions));
|
||||||
SkillSettings.Load(GetFilesOfType(ContentType.SkillSettings));
|
SkillSettings.Load(GetFilesOfType(ContentType.SkillSettings));
|
||||||
Order.Init();
|
Order.Init();
|
||||||
@@ -545,6 +557,10 @@ namespace Barotrauma
|
|||||||
TitleScreen.LoadState = 55.0f;
|
TitleScreen.LoadState = 55.0f;
|
||||||
yield return CoroutineStatus.Running;
|
yield return CoroutineStatus.Running;
|
||||||
|
|
||||||
|
UpgradePrefab.LoadAll(GetFilesOfType(ContentType.UpgradeModules));
|
||||||
|
TitleScreen.LoadState = 56.0f;
|
||||||
|
yield return CoroutineStatus.Running;
|
||||||
|
|
||||||
JobPrefab.LoadAll(GetFilesOfType(ContentType.Jobs));
|
JobPrefab.LoadAll(GetFilesOfType(ContentType.Jobs));
|
||||||
CorpsePrefab.LoadAll(GetFilesOfType(ContentType.Corpses));
|
CorpsePrefab.LoadAll(GetFilesOfType(ContentType.Corpses));
|
||||||
|
|
||||||
@@ -567,7 +583,6 @@ namespace Barotrauma
|
|||||||
yield return CoroutineStatus.Running;
|
yield return CoroutineStatus.Running;
|
||||||
|
|
||||||
MainMenuScreen = new MainMenuScreen(this);
|
MainMenuScreen = new MainMenuScreen(this);
|
||||||
LobbyScreen = new LobbyScreen();
|
|
||||||
ServerListScreen = new ServerListScreen();
|
ServerListScreen = new ServerListScreen();
|
||||||
|
|
||||||
TitleScreen.LoadState = 70.0f;
|
TitleScreen.LoadState = 70.0f;
|
||||||
@@ -594,7 +609,9 @@ namespace Barotrauma
|
|||||||
|
|
||||||
LevelEditorScreen = new LevelEditorScreen();
|
LevelEditorScreen = new LevelEditorScreen();
|
||||||
SpriteEditorScreen = new SpriteEditorScreen();
|
SpriteEditorScreen = new SpriteEditorScreen();
|
||||||
|
EventEditorScreen = new EventEditorScreen();
|
||||||
CharacterEditorScreen = new CharacterEditor.CharacterEditorScreen();
|
CharacterEditorScreen = new CharacterEditor.CharacterEditorScreen();
|
||||||
|
CampaignEndScreen = new CampaignEndScreen();
|
||||||
|
|
||||||
yield return CoroutineStatus.Running;
|
yield return CoroutineStatus.Running;
|
||||||
|
|
||||||
@@ -633,7 +650,7 @@ namespace Barotrauma
|
|||||||
foreach (ContentPackage contentPackage in Config.SelectedContentPackages)
|
foreach (ContentPackage contentPackage in Config.SelectedContentPackages)
|
||||||
{
|
{
|
||||||
var exePaths = contentPackage.GetFilesOfType(ContentType.Executable);
|
var exePaths = contentPackage.GetFilesOfType(ContentType.Executable);
|
||||||
if (exePaths.Any() && AppDomain.CurrentDomain.FriendlyName != exePaths.First())
|
if (exePaths.Any() && AppDomain.CurrentDomain.FriendlyName != Path.GetFileNameWithoutExtension(exePaths.First()))
|
||||||
{
|
{
|
||||||
var msgBox = new GUIMessageBox(TextManager.Get("Error"), TextManager.GetWithVariables("IncorrectExe",
|
var msgBox = new GUIMessageBox(TextManager.Get("Error"), TextManager.GetWithVariables("IncorrectExe",
|
||||||
new string[2] { "[selectedpackage]", "[exename]" }, new string[2] { contentPackage.Name, exePaths.First() }),
|
new string[2] { "[selectedpackage]", "[exename]" }, new string[2] { contentPackage.Name, exePaths.First() }),
|
||||||
@@ -763,7 +780,7 @@ namespace Barotrauma
|
|||||||
//reset accumulator if loading
|
//reset accumulator if loading
|
||||||
// -> less choppy loading screens because the screen is rendered after each update
|
// -> less choppy loading screens because the screen is rendered after each update
|
||||||
// -> no pause caused by leftover time in the accumulator when starting a new shift
|
// -> no pause caused by leftover time in the accumulator when starting a new shift
|
||||||
GameMain.ResetFrameTime();
|
ResetFrameTime();
|
||||||
|
|
||||||
if (!TitleScreen.PlayingSplashScreen)
|
if (!TitleScreen.PlayingSplashScreen)
|
||||||
{
|
{
|
||||||
@@ -777,11 +794,33 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
if (TitleScreen.LoadState >= 100.0f && !TitleScreen.PlayingSplashScreen && Config.AutomaticQuickStartEnabled && FirstLoad)
|
if (TitleScreen.LoadState >= 100.0f && !TitleScreen.PlayingSplashScreen && (Config.AutomaticQuickStartEnabled || Config.AutomaticCampaignLoadEnabled) && FirstLoad && !PlayerInput.KeyDown(Keys.LeftShift))
|
||||||
{
|
{
|
||||||
loadingScreenOpen = false;
|
loadingScreenOpen = false;
|
||||||
FirstLoad = false;
|
FirstLoad = false;
|
||||||
MainMenuScreen.QuickStart();
|
|
||||||
|
if (Config.AutomaticQuickStartEnabled)
|
||||||
|
{
|
||||||
|
MainMenuScreen.QuickStart();
|
||||||
|
}
|
||||||
|
else if (Config.AutomaticCampaignLoadEnabled)
|
||||||
|
{
|
||||||
|
IEnumerable<string> saveFiles = SaveUtil.GetSaveFiles(SaveUtil.SaveType.Singleplayer);
|
||||||
|
|
||||||
|
if (saveFiles.Count() > 0)
|
||||||
|
{
|
||||||
|
saveFiles = saveFiles.OrderBy(file => File.GetLastWriteTime(file));
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SaveUtil.LoadGame(saveFiles.Last());
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("Loading save \"" + saveFiles.Last() + "\" failed", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -845,6 +884,12 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
((GUIMessageBox)GUIMessageBox.VisibleBox).Close();
|
((GUIMessageBox)GUIMessageBox.VisibleBox).Close();
|
||||||
}
|
}
|
||||||
|
else if (GUIMessageBox.VisibleBox?.UserData is RoundSummary roundSummary &&
|
||||||
|
roundSummary.ContinueButton != null &&
|
||||||
|
roundSummary.ContinueButton.Visible)
|
||||||
|
{
|
||||||
|
GUIMessageBox.MessageBoxes.Remove(GUIMessageBox.VisibleBox);
|
||||||
|
}
|
||||||
else if (Tutorial.Initialized && Tutorial.ContentRunning)
|
else if (Tutorial.Initialized && Tutorial.ContentRunning)
|
||||||
{
|
{
|
||||||
(GameSession.GameMode as TutorialMode).Tutorial.CloseActiveContentGUI();
|
(GameSession.GameMode as TutorialMode).Tutorial.CloseActiveContentGUI();
|
||||||
@@ -868,7 +913,7 @@ namespace Barotrauma
|
|||||||
GUI.TogglePauseMenu();
|
GUI.TogglePauseMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool itemHudActive()
|
static bool itemHudActive()
|
||||||
{
|
{
|
||||||
if (Character.Controlled?.SelectedConstruction == null) { return false; }
|
if (Character.Controlled?.SelectedConstruction == null) { return false; }
|
||||||
return
|
return
|
||||||
@@ -878,7 +923,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
if (GameMain.NetworkMember == null)
|
if (NetworkMember == null)
|
||||||
{
|
{
|
||||||
if (PlayerInput.KeyHit(Keys.P) && !(GUI.KeyboardDispatcher.Subscriber is GUITextBox))
|
if (PlayerInput.KeyHit(Keys.P) && !(GUI.KeyboardDispatcher.Subscriber is GUITextBox))
|
||||||
{
|
{
|
||||||
@@ -890,6 +935,10 @@ namespace Barotrauma
|
|||||||
GUI.ClearUpdateList();
|
GUI.ClearUpdateList();
|
||||||
Paused = (DebugConsole.IsOpen || GUI.PauseMenuOpen || GUI.SettingsMenuOpen || Tutorial.ContentRunning || DebugConsole.Paused) &&
|
Paused = (DebugConsole.IsOpen || GUI.PauseMenuOpen || GUI.SettingsMenuOpen || Tutorial.ContentRunning || DebugConsole.Paused) &&
|
||||||
(NetworkMember == null || !NetworkMember.GameStarted);
|
(NetworkMember == null || !NetworkMember.GameStarted);
|
||||||
|
if (GameSession?.GameMode != null && GameSession.GameMode.Paused)
|
||||||
|
{
|
||||||
|
Paused = true;
|
||||||
|
}
|
||||||
|
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
if (NetworkMember == null && !WindowActive && !Paused && true && Screen.Selected != MainMenuScreen && Config.PauseOnFocusLost)
|
if (NetworkMember == null && !WindowActive && !Paused && true && Screen.Selected != MainMenuScreen && Config.PauseOnFocusLost)
|
||||||
@@ -921,7 +970,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
(GameSession.GameMode as TutorialMode).Update((float)Timing.Step);
|
(GameSession.GameMode as TutorialMode).Update((float)Timing.Step);
|
||||||
}
|
}
|
||||||
else if (DebugConsole.Paused)
|
else
|
||||||
{
|
{
|
||||||
if (Screen.Selected.Cam == null)
|
if (Screen.Selected.Cam == null)
|
||||||
{
|
{
|
||||||
@@ -929,7 +978,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Screen.Selected.Cam.MoveCamera((float)Timing.Step);
|
Screen.Selected.Cam.MoveCamera((float)Timing.Step, allowMove: DebugConsole.Paused, allowZoom: DebugConsole.Paused);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1027,41 +1076,53 @@ namespace Barotrauma
|
|||||||
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
||||||
msgBox.Buttons[1].OnClicked += msgBox.Close;
|
msgBox.Buttons[1].OnClicked += msgBox.Close;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void QuitToMainMenu(bool save)
|
public static void QuitToMainMenu(bool save)
|
||||||
{
|
{
|
||||||
if (save)
|
if (save)
|
||||||
{
|
{
|
||||||
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
|
if (GameSession.Submarine != null && !GameSession.Submarine.Removed)
|
||||||
|
{
|
||||||
|
GameSession.SubmarineInfo = new SubmarineInfo(GameSession.Submarine);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update store stock when saving and quitting in an outpost (normally updated when CampaignMode.End() is called)
|
||||||
|
if (GameSession?.Campaign is SinglePlayerCampaign campaign && Level.IsLoadedOutpost && campaign.Map?.CurrentLocation != null && campaign.CargoManager != null)
|
||||||
|
{
|
||||||
|
campaign.Map.CurrentLocation.AddToStock(campaign.CargoManager.SoldItems);
|
||||||
|
campaign.CargoManager.ClearSoldItemsProjSpecific();
|
||||||
|
campaign.Map.CurrentLocation.RemoveFromStock(campaign.CargoManager.PurchasedItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
SaveUtil.SaveGame(GameSession.SavePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameMain.Client != null)
|
if (Client != null)
|
||||||
{
|
{
|
||||||
GameMain.Client.Disconnect();
|
Client.Disconnect();
|
||||||
GameMain.Client = null;
|
Client = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
CoroutineManager.StopCoroutines("EndCinematic");
|
CoroutineManager.StopCoroutines("EndCinematic");
|
||||||
|
|
||||||
if (GameMain.GameSession != null)
|
if (GameSession != null)
|
||||||
{
|
{
|
||||||
if (Tutorial.Initialized)
|
if (Tutorial.Initialized)
|
||||||
{
|
{
|
||||||
((TutorialMode)GameMain.GameSession.GameMode).Tutorial?.Stop();
|
((TutorialMode)GameSession.GameMode).Tutorial?.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameSettings.SendUserStatistics)
|
if (GameSettings.SendUserStatistics)
|
||||||
{
|
{
|
||||||
Mission mission = GameMain.GameSession.Mission;
|
Mission mission = GameSession.Mission;
|
||||||
GameAnalyticsManager.AddDesignEvent("QuitRound:" + (save ? "Save" : "NoSave"));
|
GameAnalyticsManager.AddDesignEvent("QuitRound:" + (save ? "Save" : "NoSave"));
|
||||||
GameAnalyticsManager.AddDesignEvent("EndRound:" + (mission == null ? "NoMission" : (mission.Completed ? "MissionCompleted" : "MissionFailed")));
|
GameAnalyticsManager.AddDesignEvent("EndRound:" + (mission == null ? "NoMission" : (mission.Completed ? "MissionCompleted" : "MissionFailed")));
|
||||||
}
|
}
|
||||||
GameMain.GameSession = null;
|
|
||||||
}
|
}
|
||||||
GUIMessageBox.CloseAll();
|
GUIMessageBox.CloseAll();
|
||||||
GameMain.MainMenuScreen.Select();
|
MainMenuScreen.Select();
|
||||||
|
GameSession = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ShowCampaignDisclaimer(Action onContinue = null)
|
public void ShowCampaignDisclaimer(Action onContinue = null)
|
||||||
@@ -1071,12 +1132,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
msgBox.Buttons[0].OnClicked = (btn, userdata) =>
|
msgBox.Buttons[0].OnClicked = (btn, userdata) =>
|
||||||
{
|
{
|
||||||
var roadMap = new GUIMessageBox(TextManager.Get("CampaignRoadMapTitle"), TextManager.Get("CampaignRoadMapText"),
|
ShowOpenUrlInWebBrowserPrompt("https://trello.com/b/hBXI8ltN/barotrauma-roadmap-known-issues");
|
||||||
new string[] { TextManager.Get("Back"), TextManager.Get("OK") });
|
|
||||||
roadMap.Buttons[0].OnClicked += roadMap.Close;
|
|
||||||
roadMap.Buttons[0].OnClicked += (_, __) => { ShowCampaignDisclaimer(onContinue); return true; };
|
|
||||||
roadMap.Buttons[1].OnClicked += roadMap.Close;
|
|
||||||
roadMap.Buttons[1].OnClicked += (_, __) => { onContinue?.Invoke(); return true; };
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
||||||
@@ -1094,9 +1150,9 @@ namespace Barotrauma
|
|||||||
linkHolder.RectTransform.MaxSize = new Point(int.MaxValue, linkHolder.Rect.Height);
|
linkHolder.RectTransform.MaxSize = new Point(int.MaxValue, linkHolder.Rect.Height);
|
||||||
List<Pair<string, string>> links = new List<Pair<string, string>>()
|
List<Pair<string, string>> links = new List<Pair<string, string>>()
|
||||||
{
|
{
|
||||||
new Pair<string, string>(TextManager.Get("EditorDisclaimerWikiLink"),TextManager.Get("EditorDisclaimerWikiUrl")),
|
new Pair<string, string>(TextManager.Get("EditorDisclaimerWikiLink"), TextManager.Get("EditorDisclaimerWikiUrl")),
|
||||||
new Pair<string, string>(TextManager.Get("EditorDisclaimerDiscordLink"),TextManager.Get("EditorDisclaimerDiscordUrl")),
|
new Pair<string, string>(TextManager.Get("EditorDisclaimerDiscordLink"), TextManager.Get("EditorDisclaimerDiscordUrl")),
|
||||||
new Pair<string, string>(TextManager.Get("EditorDisclaimerForumLink"),TextManager.Get("EditorDisclaimerForumUrl")),
|
new Pair<string, string>(TextManager.Get("EditorDisclaimerForumLink"), TextManager.Get("EditorDisclaimerForumUrl")),
|
||||||
};
|
};
|
||||||
foreach (var link in links)
|
foreach (var link in links)
|
||||||
{
|
{
|
||||||
@@ -1124,8 +1180,10 @@ namespace Barotrauma
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var msgBox = new GUIMessageBox(TextManager.Get("bugreportbutton"), "");
|
var msgBox = new GUIMessageBox(TextManager.Get("bugreportbutton"), "")
|
||||||
msgBox.UserData = "bugreporter";
|
{
|
||||||
|
UserData = "bugreporter"
|
||||||
|
};
|
||||||
var linkHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), msgBox.Content.RectTransform)) { Stretch = true, RelativeSpacing = 0.025f };
|
var linkHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), msgBox.Content.RectTransform)) { Stretch = true, RelativeSpacing = 0.025f };
|
||||||
linkHolder.RectTransform.MaxSize = new Point(int.MaxValue, linkHolder.Rect.Height);
|
linkHolder.RectTransform.MaxSize = new Point(int.MaxValue, linkHolder.Rect.Height);
|
||||||
|
|
||||||
@@ -1189,7 +1247,7 @@ namespace Barotrauma
|
|||||||
DebugConsole.ThrowError("Error while cleaning unnecessary save files", e);
|
DebugConsole.ThrowError("Error while cleaning unnecessary save files", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameSettings.SendUserStatistics){ GameAnalytics.OnQuit(); }
|
if (GameSettings.SendUserStatistics) { GameAnalytics.OnQuit(); }
|
||||||
if (GameSettings.SaveDebugConsoleLogs) { DebugConsole.SaveLogs(); }
|
if (GameSettings.SaveDebugConsoleLogs) { DebugConsole.SaveLogs(); }
|
||||||
|
|
||||||
base.OnExiting(sender, args);
|
base.OnExiting(sender, args);
|
||||||
|
|||||||
@@ -0,0 +1,173 @@
|
|||||||
|
using Barotrauma.Extensions;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
partial class CargoManager
|
||||||
|
{
|
||||||
|
private class SoldEntity
|
||||||
|
{
|
||||||
|
public enum SellStatus
|
||||||
|
{
|
||||||
|
Confirmed,
|
||||||
|
Unconfirmed,
|
||||||
|
Local
|
||||||
|
}
|
||||||
|
|
||||||
|
public Item Item { get; }
|
||||||
|
public SellStatus Status { get; set; }
|
||||||
|
|
||||||
|
private SoldEntity(Item item, SellStatus status)
|
||||||
|
{
|
||||||
|
Item = item;
|
||||||
|
Status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SoldEntity CreateInSinglePlayer(Item item) => new SoldEntity(item, SellStatus.Confirmed);
|
||||||
|
public static SoldEntity CreateInMultiPlayer(Item item) => new SoldEntity(item, SellStatus.Local);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<SoldEntity> SoldEntities { get; } = new List<SoldEntity>();
|
||||||
|
|
||||||
|
public List<Item> GetSellableItems(Character character)
|
||||||
|
{
|
||||||
|
if (character == null) { return new List<Item>(); }
|
||||||
|
|
||||||
|
// Only consider items which have been:
|
||||||
|
// a) sold in singleplayer or confirmed by server (SellStatus.Confirmed); or
|
||||||
|
// b) sold locally in multiplier (SellStatus.Local), but the client has not received a campaing state update yet after selling them
|
||||||
|
var soldEntities = SoldEntities.Where(se => se.Status != SoldEntity.SellStatus.Unconfirmed);
|
||||||
|
|
||||||
|
var sellables = Item.ItemList.FindAll(i => i?.Prefab != null && !i.Removed &&
|
||||||
|
i.GetRootInventoryOwner() == character &&
|
||||||
|
!i.SpawnedInOutpost &&
|
||||||
|
(i.ContainedItems == null || i.ContainedItems.None() || i.ContainedItems.All(ci => soldEntities.Any(se => se.Item == ci))) &&
|
||||||
|
i.IsFullCondition && soldEntities.None(se => se.Item == i));
|
||||||
|
|
||||||
|
// Prevent selling things like battery cells from headsets and oxygen tanks from diving masks
|
||||||
|
var slots = new List<InvSlotType>() { InvSlotType.Head, InvSlotType.OuterClothes, InvSlotType.Headset };
|
||||||
|
foreach (InvSlotType slot in slots)
|
||||||
|
{
|
||||||
|
var index = character.Inventory.FindLimbSlot(slot);
|
||||||
|
if (character.Inventory.Items[index] is Item item && item.ContainedItems != null)
|
||||||
|
{
|
||||||
|
foreach (Item containedItem in item.ContainedItems)
|
||||||
|
{
|
||||||
|
if (containedItem != null)
|
||||||
|
{
|
||||||
|
sellables.Remove(containedItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sellables;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetItemsInBuyCrate(List<PurchasedItem> items)
|
||||||
|
{
|
||||||
|
ItemsInBuyCrate.Clear();
|
||||||
|
ItemsInBuyCrate.AddRange(items);
|
||||||
|
OnItemsInBuyCrateChanged?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetSoldItems(List<SoldItem> items)
|
||||||
|
{
|
||||||
|
SoldItems.Clear();
|
||||||
|
SoldItems.AddRange(items);
|
||||||
|
|
||||||
|
foreach (SoldEntity se in SoldEntities)
|
||||||
|
{
|
||||||
|
if (se.Status == SoldEntity.SellStatus.Confirmed) { continue; }
|
||||||
|
if (SoldItems.Any(si => si.ID == se.Item.ID && si.ItemPrefab == se.Item.Prefab && (GameMain.Client == null || GameMain.Client.ID == si.SellerID)))
|
||||||
|
{
|
||||||
|
se.Status = SoldEntity.SellStatus.Confirmed;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
se.Status = SoldEntity.SellStatus.Unconfirmed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OnSoldItemsChanged?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ModifyItemQuantityInSellCrate(ItemPrefab itemPrefab, int changeInQuantity)
|
||||||
|
{
|
||||||
|
PurchasedItem itemToSell = ItemsInSellCrate.Find(i => i.ItemPrefab == itemPrefab);
|
||||||
|
if (itemToSell != null)
|
||||||
|
{
|
||||||
|
itemToSell.Quantity += changeInQuantity;
|
||||||
|
if (itemToSell.Quantity < 1)
|
||||||
|
{
|
||||||
|
ItemsInSellCrate.Remove(itemToSell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (changeInQuantity > 0)
|
||||||
|
{
|
||||||
|
itemToSell = new PurchasedItem(itemPrefab, changeInQuantity);
|
||||||
|
ItemsInSellCrate.Add(itemToSell);
|
||||||
|
}
|
||||||
|
OnItemsInSellCrateChanged?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SellItems(List<PurchasedItem> itemsToSell)
|
||||||
|
{
|
||||||
|
var itemsInInventory = GetSellableItems(Character.Controlled);
|
||||||
|
var canAddToRemoveQueue = campaign.IsSinglePlayer && Entity.Spawner != null;
|
||||||
|
var sellerId = GameMain.Client?.ID ?? 0;
|
||||||
|
|
||||||
|
foreach (PurchasedItem item in itemsToSell)
|
||||||
|
{
|
||||||
|
var itemValue = GetSellValueAtCurrentLocation(item.ItemPrefab, quantity: item.Quantity);
|
||||||
|
|
||||||
|
// check if the store can afford the item
|
||||||
|
if (location.StoreCurrentBalance < itemValue) { continue; }
|
||||||
|
|
||||||
|
var matchingItems = itemsInInventory.FindAll(i => i.Prefab == item.ItemPrefab);
|
||||||
|
if (matchingItems.Count <= item.Quantity)
|
||||||
|
{
|
||||||
|
foreach (Item i in matchingItems)
|
||||||
|
{
|
||||||
|
SoldItems.Add(new SoldItem(i.Prefab, i.ID, canAddToRemoveQueue, sellerId));
|
||||||
|
SoldEntities.Add(campaign.IsSinglePlayer ? SoldEntity.CreateInSinglePlayer(i) : SoldEntity.CreateInMultiPlayer(i));
|
||||||
|
if (canAddToRemoveQueue) { Entity.Spawner.AddToRemoveQueue(i); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < item.Quantity; i++)
|
||||||
|
{
|
||||||
|
var matchingItem = matchingItems[i];
|
||||||
|
SoldItems.Add(new SoldItem(matchingItem.Prefab, matchingItem.ID, canAddToRemoveQueue, sellerId));
|
||||||
|
SoldEntities.Add(campaign.IsSinglePlayer ? SoldEntity.CreateInSinglePlayer(matchingItem) : SoldEntity.CreateInMultiPlayer(matchingItem));
|
||||||
|
if (canAddToRemoveQueue) { Entity.Spawner.AddToRemoveQueue(matchingItem); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exchange money
|
||||||
|
campaign.Map.CurrentLocation.StoreCurrentBalance -= itemValue;
|
||||||
|
campaign.Money += itemValue;
|
||||||
|
|
||||||
|
// Remove from the sell crate
|
||||||
|
if (ItemsInSellCrate.Find(pi => pi.ItemPrefab == item.ItemPrefab) is { } itemToSell)
|
||||||
|
{
|
||||||
|
itemToSell.Quantity -= item.Quantity;
|
||||||
|
if (itemToSell.Quantity < 1)
|
||||||
|
{
|
||||||
|
ItemsInSellCrate.Remove(itemToSell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OnSoldItemsChanged?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearSoldItemsProjSpecific()
|
||||||
|
{
|
||||||
|
SoldItems.Clear();
|
||||||
|
SoldEntities.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,9 +20,6 @@ namespace Barotrauma
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
const float CharacterWaitOnSwitch = 10.0f;
|
const float CharacterWaitOnSwitch = 10.0f;
|
||||||
|
|
||||||
private readonly List<CharacterInfo> characterInfos = new List<CharacterInfo>();
|
|
||||||
private readonly List<Character> characters = new List<Character>();
|
|
||||||
|
|
||||||
private Point screenResolution;
|
private Point screenResolution;
|
||||||
|
|
||||||
#region UI
|
#region UI
|
||||||
@@ -30,6 +27,7 @@ namespace Barotrauma
|
|||||||
public GUIComponent ReportButtonFrame { get; set; }
|
public GUIComponent ReportButtonFrame { get; set; }
|
||||||
|
|
||||||
private GUIFrame guiFrame;
|
private GUIFrame guiFrame;
|
||||||
|
private GUIComponent crewAreaWithButtons;
|
||||||
private GUIFrame crewArea;
|
private GUIFrame crewArea;
|
||||||
private GUIListBox crewList;
|
private GUIListBox crewList;
|
||||||
private GUIButton commandButton, toggleCrewButton;
|
private GUIButton commandButton, toggleCrewButton;
|
||||||
@@ -72,19 +70,7 @@ namespace Barotrauma
|
|||||||
public CrewManager(XElement element, bool isSinglePlayer)
|
public CrewManager(XElement element, bool isSinglePlayer)
|
||||||
: this(isSinglePlayer)
|
: this(isSinglePlayer)
|
||||||
{
|
{
|
||||||
foreach (XElement subElement in element.Elements())
|
AddCharacterElements(element);
|
||||||
{
|
|
||||||
if (!subElement.Name.ToString().Equals("character", StringComparison.OrdinalIgnoreCase)) { continue; }
|
|
||||||
|
|
||||||
var characterInfo = new CharacterInfo(subElement);
|
|
||||||
characterInfos.Add(characterInfo);
|
|
||||||
foreach (XElement invElement in subElement.Elements())
|
|
||||||
{
|
|
||||||
if (!invElement.Name.ToString().Equals("inventory", StringComparison.OrdinalIgnoreCase)) { continue; }
|
|
||||||
characterInfo.InventoryData = invElement;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void InitProjectSpecific()
|
partial void InitProjectSpecific()
|
||||||
@@ -96,7 +82,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
#region Crew Area
|
#region Crew Area
|
||||||
|
|
||||||
var crewAreaWithButtons = new GUIFrame(
|
crewAreaWithButtons = new GUIFrame(
|
||||||
HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.CrewArea, guiFrame.RectTransform),
|
HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.CrewArea, guiFrame.RectTransform),
|
||||||
style: null,
|
style: null,
|
||||||
color: Color.Transparent)
|
color: Color.Transparent)
|
||||||
@@ -326,43 +312,6 @@ namespace Barotrauma
|
|||||||
return characterInfos;
|
return characterInfos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddCharacter(Character character)
|
|
||||||
{
|
|
||||||
if (character.Removed)
|
|
||||||
{
|
|
||||||
DebugConsole.ThrowError("Tried to add a removed character to CrewManager!\n" + Environment.StackTrace);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (character.IsDead)
|
|
||||||
{
|
|
||||||
DebugConsole.ThrowError("Tried to add a dead character to CrewManager!\n" + Environment.StackTrace);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!characters.Contains(character))
|
|
||||||
{
|
|
||||||
characters.Add(character);
|
|
||||||
}
|
|
||||||
if (!characterInfos.Contains(character.Info))
|
|
||||||
{
|
|
||||||
characterInfos.Add(character.Info);
|
|
||||||
}
|
|
||||||
|
|
||||||
AddCharacterToCrewList(character);
|
|
||||||
DisplayCharacterOrder(character, character.CurrentOrder, character.CurrentOrderOption);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddCharacterInfo(CharacterInfo characterInfo)
|
|
||||||
{
|
|
||||||
if (characterInfos.Contains(characterInfo))
|
|
||||||
{
|
|
||||||
DebugConsole.ThrowError("Tried to add the same character info to CrewManager twice.\n" + Environment.StackTrace);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
characterInfos.Add(characterInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Remove the character from the crew (and crew menus).
|
/// Remove the character from the crew (and crew menus).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -379,15 +328,6 @@ namespace Barotrauma
|
|||||||
if (removeInfo) { characterInfos.Remove(character.Info); }
|
if (removeInfo) { characterInfos.Remove(character.Info); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Remove info of a selected character. The character will not be visible in any menus or the round summary.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="characterInfo"></param>
|
|
||||||
public void RemoveCharacterInfo(CharacterInfo characterInfo)
|
|
||||||
{
|
|
||||||
characterInfos.Remove(characterInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddCharacterToCrewList(Character character)
|
private void AddCharacterToCrewList(Character character)
|
||||||
{
|
{
|
||||||
if (character == null) { return; }
|
if (character == null) { return; }
|
||||||
@@ -516,7 +456,7 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
new GUIImage(
|
new GUIImage(
|
||||||
new RectTransform(Vector2.One, soundIcons.RectTransform),
|
new RectTransform(Vector2.One, soundIcons.RectTransform),
|
||||||
GUI.Style.GetComponentStyle("GUISoundIcon").Sprites[GUIComponent.ComponentState.None].FirstOrDefault().Sprite,
|
GUI.Style.GetComponentStyle("GUISoundIcon").GetDefaultSprite(),
|
||||||
scaleToFit: true)
|
scaleToFit: true)
|
||||||
{
|
{
|
||||||
CanBeFocused = false,
|
CanBeFocused = false,
|
||||||
@@ -630,6 +570,22 @@ namespace Barotrauma
|
|||||||
ChatBox.AddMessage(ChatMessage.Create(senderName, text, messageType, sender));
|
ChatBox.AddMessage(ChatMessage.Create(senderName, text, messageType, sender));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddSinglePlayerChatMessage(ChatMessage message)
|
||||||
|
{
|
||||||
|
if (!IsSinglePlayer)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("Cannot add messages to single player chat box in multiplayer mode!\n" + Environment.StackTrace);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(message.Text)) { return; }
|
||||||
|
|
||||||
|
if (message.Sender != null)
|
||||||
|
{
|
||||||
|
GameMain.GameSession.CrewManager.SetCharacterSpeaking(message.Sender);
|
||||||
|
}
|
||||||
|
ChatBox.AddMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
private WifiComponent GetHeadset(Character character, bool requireEquipped)
|
private WifiComponent GetHeadset(Character character, bool requireEquipped)
|
||||||
{
|
{
|
||||||
if (character?.Inventory == null) return null;
|
if (character?.Inventory == null) return null;
|
||||||
@@ -861,27 +817,6 @@ namespace Barotrauma
|
|||||||
return characterComponent?.FindChild(c => c?.UserData is OrderInfo orderInfo && orderInfo.ComponentIdentifier == "previousorder");
|
return characterComponent?.FindChild(c => c?.UserData is OrderInfo orderInfo && orderInfo.ComponentIdentifier == "previousorder");
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct OrderInfo
|
|
||||||
{
|
|
||||||
public string ComponentIdentifier { get; set; }
|
|
||||||
public Order Order { get; private set; }
|
|
||||||
public string OrderOption { get; private set; }
|
|
||||||
|
|
||||||
public OrderInfo(Order order, string orderOption)
|
|
||||||
{
|
|
||||||
ComponentIdentifier = "currentorder";
|
|
||||||
Order = order;
|
|
||||||
OrderOption = orderOption;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OrderInfo(OrderInfo orderInfo)
|
|
||||||
{
|
|
||||||
ComponentIdentifier = "previousorder";
|
|
||||||
Order = orderInfo.Order;
|
|
||||||
OrderOption = orderInfo.OrderOption;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Updating and drawing the UI
|
#region Updating and drawing the UI
|
||||||
@@ -1123,6 +1058,7 @@ namespace Barotrauma
|
|||||||
public void AddToGUIUpdateList()
|
public void AddToGUIUpdateList()
|
||||||
{
|
{
|
||||||
if (GUI.DisableHUD) { return; }
|
if (GUI.DisableHUD) { return; }
|
||||||
|
if (CoroutineManager.IsCoroutineRunning("LevelTransition") || CoroutineManager.IsCoroutineRunning("SubmarineTransition")) { return; }
|
||||||
|
|
||||||
commandFrame?.AddToGUIUpdateList();
|
commandFrame?.AddToGUIUpdateList();
|
||||||
|
|
||||||
@@ -1145,6 +1081,8 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
crewAreaWithButtons.Visible = !(GameMain.GameSession?.GameMode is CampaignMode campaign) || (!campaign.ForceMapUI && !campaign.ShowCampaignUI);
|
||||||
|
|
||||||
guiFrame.AddToGUIUpdateList();
|
guiFrame.AddToGUIUpdateList();
|
||||||
contextMenu?.AddToGUIUpdateList(false, 1);
|
contextMenu?.AddToGUIUpdateList(false, 1);
|
||||||
subContextMenu?.AddToGUIUpdateList(false, 1);
|
subContextMenu?.AddToGUIUpdateList(false, 1);
|
||||||
@@ -1170,6 +1108,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private void SelectCharacter(Character character)
|
private void SelectCharacter(Character character)
|
||||||
{
|
{
|
||||||
|
if (ConversationAction.IsDialogOpen) { return; }
|
||||||
if (!AllowCharacterSwitch) { return; }
|
if (!AllowCharacterSwitch) { return; }
|
||||||
//make the previously selected character wait in place for some time
|
//make the previously selected character wait in place for some time
|
||||||
//(so they don't immediately start idling and walking away from their station)
|
//(so they don't immediately start idling and walking away from their station)
|
||||||
@@ -1256,7 +1195,7 @@ namespace Barotrauma
|
|||||||
WasCommandInterfaceDisabledThisUpdate = false;
|
WasCommandInterfaceDisabledThisUpdate = false;
|
||||||
|
|
||||||
if (PlayerInput.KeyDown(InputType.Command) && (GUI.KeyboardDispatcher.Subscriber == null || GUI.KeyboardDispatcher.Subscriber == crewList) &&
|
if (PlayerInput.KeyDown(InputType.Command) && (GUI.KeyboardDispatcher.Subscriber == null || GUI.KeyboardDispatcher.Subscriber == crewList) &&
|
||||||
commandFrame == null && !clicklessSelectionActive && CanIssueOrders)
|
commandFrame == null && !clicklessSelectionActive && CanIssueOrders && !(GameMain.GameSession?.Campaign?.ShowCampaignUI ?? false))
|
||||||
{
|
{
|
||||||
if (PlayerInput.KeyDown(Keys.LeftShift) || PlayerInput.KeyDown(Keys.RightShift))
|
if (PlayerInput.KeyDown(Keys.LeftShift) || PlayerInput.KeyDown(Keys.RightShift))
|
||||||
{
|
{
|
||||||
@@ -1574,32 +1513,32 @@ namespace Barotrauma
|
|||||||
get
|
get
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
return Character.Controlled == null || Character.Controlled.Info != null && Character.Controlled.SpeechImpediment < 100.0f;
|
if (Character.Controlled == null) { return true; }
|
||||||
#else
|
|
||||||
return Character.Controlled?.Info != null && Character.Controlled.SpeechImpediment < 100.0f;
|
|
||||||
#endif
|
#endif
|
||||||
|
return Character.Controlled?.Info != null && Character.Controlled.SpeechImpediment < 100.0f;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool CanSomeoneHearCharacter()
|
private bool CanSomeoneHearCharacter()
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
return true;
|
if (Character.Controlled == null) { return true; }
|
||||||
#else
|
|
||||||
return Character.Controlled != null && characters.Any(c => c != Character.Controlled && c.CanHearCharacter(Character.Controlled));
|
|
||||||
#endif
|
#endif
|
||||||
|
return Character.Controlled != null && characters.Any(c => c != Character.Controlled && c.CanHearCharacter(Character.Controlled));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Entity FindEntityContext()
|
private Entity FindEntityContext()
|
||||||
{
|
{
|
||||||
if (Character.Controlled?.FocusedCharacter != null)
|
if (Character.Controlled?.FocusedCharacter is Character focusedCharacter && !focusedCharacter.IsDead &&
|
||||||
|
HumanAIController.IsFriendly(Character.Controlled, focusedCharacter) && Character.Controlled.TeamID == focusedCharacter.TeamID)
|
||||||
{
|
{
|
||||||
if (Character.Controlled?.FocusedItem != null)
|
if (Character.Controlled?.FocusedItem != null)
|
||||||
{
|
{
|
||||||
Vector2 mousePos = GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
|
Vector2 mousePos = GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||||
if (Vector2.Distance(mousePos, Character.Controlled.FocusedCharacter.WorldPosition) < Vector2.Distance(mousePos, Character.Controlled.FocusedItem.WorldPosition))
|
if (Vector2.Distance(mousePos, focusedCharacter.WorldPosition) < Vector2.Distance(mousePos, Character.Controlled.FocusedItem.WorldPosition))
|
||||||
{
|
{
|
||||||
return Character.Controlled.FocusedCharacter;
|
return focusedCharacter;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1608,7 +1547,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return Character.Controlled.FocusedCharacter;
|
return focusedCharacter;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1677,24 +1616,22 @@ namespace Barotrauma
|
|||||||
"CommandNodeContainer",
|
"CommandNodeContainer",
|
||||||
scaleToFit: true)
|
scaleToFit: true)
|
||||||
{
|
{
|
||||||
Color = characterContext.Info.Job.Prefab.UIColor * nodeColorMultiplier,
|
Color = characterContext.Info?.Job?.Prefab != null ? characterContext.Info.Job.Prefab.UIColor * nodeColorMultiplier : Color.White,
|
||||||
HoverColor = characterContext.Info.Job.Prefab.UIColor,
|
HoverColor = characterContext.Info?.Job?.Prefab != null ? characterContext.Info.Job.Prefab.UIColor : Color.White,
|
||||||
UserData = "colorsource"
|
UserData = "colorsource"
|
||||||
};
|
};
|
||||||
// Character icon
|
// Character icon
|
||||||
new GUICustomComponent(
|
var characterIcon = new GUICustomComponent(
|
||||||
new RectTransform(Vector2.One, startNode.RectTransform, anchor: Anchor.Center),
|
new RectTransform(Vector2.One, startNode.RectTransform, anchor: Anchor.Center),
|
||||||
(spriteBatch, _) =>
|
(spriteBatch, _) =>
|
||||||
{
|
{
|
||||||
if (!(entityContext is Character character)) { return; }
|
if (!(entityContext is Character character) || character?.Info == null) { return; }
|
||||||
var node = startNode;
|
var node = startNode;
|
||||||
character.Info.DrawJobIcon(spriteBatch,
|
character.Info.DrawJobIcon(spriteBatch,
|
||||||
new Rectangle((int)(node.Rect.X + node.Rect.Width * 0.5f), (int)(node.Rect.Y + node.Rect.Height * 0.1f), (int)(node.Rect.Width * 0.6f), (int)(node.Rect.Height * 0.8f)));
|
new Rectangle((int)(node.Rect.X + node.Rect.Width * 0.5f), (int)(node.Rect.Y + node.Rect.Height * 0.1f), (int)(node.Rect.Width * 0.6f), (int)(node.Rect.Height * 0.8f)));
|
||||||
character.Info.DrawIcon(spriteBatch, new Vector2(node.Rect.X + node.Rect.Width * 0.35f, node.Center.Y), node.Rect.Size.ToVector2() * 0.7f);
|
character.Info.DrawIcon(spriteBatch, new Vector2(node.Rect.X + node.Rect.Width * 0.35f, node.Center.Y), node.Rect.Size.ToVector2() * 0.7f);
|
||||||
})
|
});
|
||||||
{
|
SetCharacterTooltip(characterIcon, entityContext as Character);
|
||||||
ToolTip = characterContext.Info.DisplayName + " (" + characterContext.Info.Job.Name + ")"
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
SetCenterNode(startNode);
|
SetCenterNode(startNode);
|
||||||
|
|
||||||
@@ -1934,7 +1871,7 @@ namespace Barotrauma
|
|||||||
c.HoverColor = c.Color;
|
c.HoverColor = c.Color;
|
||||||
c.PressedColor = c.Color;
|
c.PressedColor = c.Color;
|
||||||
c.SelectedColor = c.Color;
|
c.SelectedColor = c.Color;
|
||||||
c.ToolTip = characterContext != null ? characterContext.Info.DisplayName + " (" + characterContext.Info.Job.Name + ")" : null;
|
SetCharacterTooltip(c, characterContext);
|
||||||
}
|
}
|
||||||
node.OnClicked = null;
|
node.OnClicked = null;
|
||||||
centerNode = node;
|
centerNode = node;
|
||||||
@@ -2040,7 +1977,7 @@ namespace Barotrauma
|
|||||||
var reactorOutput = -reactor.CurrPowerConsumption;
|
var reactorOutput = -reactor.CurrPowerConsumption;
|
||||||
// If player is not an engineer AND the reactor is not powered up AND nobody is using the reactor
|
// If player is not an engineer AND the reactor is not powered up AND nobody is using the reactor
|
||||||
// ---> Create shortcut node for "Operate Reactor" order's "Power Up" option
|
// ---> Create shortcut node for "Operate Reactor" order's "Power Up" option
|
||||||
if ((Character.Controlled == null || Character.Controlled.Info.Job.Prefab != JobPrefab.Get("engineer")) &&
|
if ((Character.Controlled == null || Character.Controlled.Info?.Job?.Prefab != JobPrefab.Get("engineer")) &&
|
||||||
reactorOutput < float.Epsilon && characters.None(c => c.SelectedConstruction == reactor.Item))
|
reactorOutput < float.Epsilon && characters.None(c => c.SelectedConstruction == reactor.Item))
|
||||||
{
|
{
|
||||||
var order = new Order(Order.GetPrefab("operatereactor"), reactor.Item, reactor, Character.Controlled);
|
var order = new Order(Order.GetPrefab("operatereactor"), reactor.Item, reactor, Character.Controlled);
|
||||||
@@ -2053,7 +1990,7 @@ namespace Barotrauma
|
|||||||
// TODO: Reconsider the conditions as bot captain can have the nav term selected without operating it
|
// TODO: Reconsider the conditions as bot captain can have the nav term selected without operating it
|
||||||
// If player is not a captain AND nobody is using the nav terminal AND the nav terminal is powered up
|
// If player is not a captain AND nobody is using the nav terminal AND the nav terminal is powered up
|
||||||
// --> Create shortcut node for Steer order
|
// --> Create shortcut node for Steer order
|
||||||
if (shortcutNodes.Count < maxShorcutNodeCount && (Character.Controlled == null || Character.Controlled.Info.Job.Prefab != JobPrefab.Get("captain")) &&
|
if (shortcutNodes.Count < maxShorcutNodeCount && (Character.Controlled == null || Character.Controlled.Info?.Job?.Prefab != JobPrefab.Get("captain")) &&
|
||||||
sub.GetItems(false).Find(i => i.HasTag("navterminal") && !i.NonInteractable) is Item nav && characters.None(c => c.SelectedConstruction == nav) &&
|
sub.GetItems(false).Find(i => i.HasTag("navterminal") && !i.NonInteractable) is Item nav && characters.None(c => c.SelectedConstruction == nav) &&
|
||||||
nav.GetComponent<Steering>() is Steering steering && steering.Voltage > steering.MinVoltage)
|
nav.GetComponent<Steering>() is Steering steering && steering.Voltage > steering.MinVoltage)
|
||||||
{
|
{
|
||||||
@@ -2063,7 +2000,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
// If player is not a security officer AND invaders are reported
|
// If player is not a security officer AND invaders are reported
|
||||||
// --> Create shorcut node for Fight Intruders order
|
// --> Create shorcut node for Fight Intruders order
|
||||||
if (shortcutNodes.Count < maxShorcutNodeCount && (Character.Controlled == null || Character.Controlled.Info.Job.Prefab != JobPrefab.Get("securityofficer")) &&
|
if (shortcutNodes.Count < maxShorcutNodeCount && (Character.Controlled == null || Character.Controlled.Info?.Job?.Prefab != JobPrefab.Get("securityofficer")) &&
|
||||||
(Order.GetPrefab("reportintruders") is Order reportIntruders && ActiveOrders.Any(o => o.First.Prefab == reportIntruders)))
|
(Order.GetPrefab("reportintruders") is Order reportIntruders && ActiveOrders.Any(o => o.First.Prefab == reportIntruders)))
|
||||||
{
|
{
|
||||||
shortcutNodes.Add(
|
shortcutNodes.Add(
|
||||||
@@ -2072,7 +2009,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
// If player is not a mechanic AND a breach has been reported
|
// If player is not a mechanic AND a breach has been reported
|
||||||
// --> Create shorcut node for Fix Leaks order
|
// --> Create shorcut node for Fix Leaks order
|
||||||
if (shortcutNodes.Count < maxShorcutNodeCount && (Character.Controlled == null || Character.Controlled.Info.Job.Prefab != JobPrefab.Get("mechanic")) &&
|
if (shortcutNodes.Count < maxShorcutNodeCount && (Character.Controlled == null || Character.Controlled.Info?.Job?.Prefab != JobPrefab.Get("mechanic")) &&
|
||||||
(Order.GetPrefab("reportbreach") is Order reportBreach && ActiveOrders.Any(o => o.First.Prefab == reportBreach)))
|
(Order.GetPrefab("reportbreach") is Order reportBreach && ActiveOrders.Any(o => o.First.Prefab == reportBreach)))
|
||||||
{
|
{
|
||||||
shortcutNodes.Add(
|
shortcutNodes.Add(
|
||||||
@@ -2081,7 +2018,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
// If player is not an engineer AND broken devices have been reported
|
// If player is not an engineer AND broken devices have been reported
|
||||||
// --> Create shortcut node for Repair Damaged Systems order
|
// --> Create shortcut node for Repair Damaged Systems order
|
||||||
if (shortcutNodes.Count < maxShorcutNodeCount && (Character.Controlled == null || Character.Controlled.Info.Job.Prefab != JobPrefab.Get("engineer")) &&
|
if (shortcutNodes.Count < maxShorcutNodeCount && (Character.Controlled == null || Character.Controlled.Info?.Job?.Prefab != JobPrefab.Get("engineer")) &&
|
||||||
(Order.GetPrefab("reportbrokendevices") is Order reportBrokenDevices && ActiveOrders.Any(o => o.First.Prefab == reportBrokenDevices)))
|
(Order.GetPrefab("reportbrokendevices") is Order reportBrokenDevices && ActiveOrders.Any(o => o.First.Prefab == reportBrokenDevices)))
|
||||||
{
|
{
|
||||||
shortcutNodes.Add(
|
shortcutNodes.Add(
|
||||||
@@ -2741,11 +2678,11 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
bool canHear = true;
|
|
||||||
#else
|
|
||||||
bool canHear = character.CanHearCharacter(Character.Controlled);
|
bool canHear = character.CanHearCharacter(Character.Controlled);
|
||||||
|
#if DEBUG
|
||||||
|
if (Character.Controlled == null) { canHear = true; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!canHear)
|
if (!canHear)
|
||||||
{
|
{
|
||||||
node.CanBeFocused = orderIcon.CanBeFocused = false;
|
node.CanBeFocused = orderIcon.CanBeFocused = false;
|
||||||
@@ -2904,18 +2841,29 @@ namespace Barotrauma
|
|||||||
return sub;
|
return sub;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetCharacterTooltip(GUIComponent component, Character character)
|
||||||
|
{
|
||||||
|
if (component == null) { return; }
|
||||||
|
var tooltip = character?.Info != null ? characterContext.Info.DisplayName : null;
|
||||||
|
if (string.IsNullOrWhiteSpace(tooltip)) { component.ToolTip = tooltip; return; }
|
||||||
|
if (character.Info?.Job != null && !string.IsNullOrWhiteSpace(characterContext.Info.Job.Name)) { tooltip += " (" + characterContext.Info.Job.Name + ")"; }
|
||||||
|
component.ToolTip = tooltip;
|
||||||
|
}
|
||||||
|
|
||||||
#region Crew Member Assignment Logic
|
#region Crew Member Assignment Logic
|
||||||
|
|
||||||
private Character GetCharacterForQuickAssignment(Order order)
|
private Character GetCharacterForQuickAssignment(Order order)
|
||||||
{
|
{
|
||||||
|
var controllingCharacter = Character.Controlled != null;
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
if (Character.Controlled == null) { return null; }
|
if (!controllingCharacter) { return null; }
|
||||||
#endif
|
#endif
|
||||||
if (order.Category == OrderCategory.Operate && HumanAIController.IsItemOperatedByAnother(null, order.TargetItemComponent, out Character operatingCharacter))
|
if (order.Category == OrderCategory.Operate && HumanAIController.IsItemOperatedByAnother(null, order.TargetItemComponent, out Character operatingCharacter) &&
|
||||||
|
(!controllingCharacter || operatingCharacter.CanHearCharacter(Character.Controlled)))
|
||||||
{
|
{
|
||||||
return operatingCharacter;
|
return operatingCharacter;
|
||||||
}
|
}
|
||||||
return GetCharactersSortedForOrder(order, false).FirstOrDefault() ?? Character.Controlled;
|
return GetCharactersSortedForOrder(order, false).FirstOrDefault(c => !controllingCharacter || c.CanHearCharacter(Character.Controlled)) ?? Character.Controlled;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Character> GetCharactersForManualAssignment(Order order)
|
private List<Character> GetCharactersForManualAssignment(Order order)
|
||||||
@@ -2934,11 +2882,17 @@ namespace Barotrauma
|
|||||||
private IEnumerable<Character> GetCharactersSortedForOrder(Order order, bool includeSelf)
|
private IEnumerable<Character> GetCharactersSortedForOrder(Order order, bool includeSelf)
|
||||||
{
|
{
|
||||||
return characters.FindAll(c => Character.Controlled == null || ((includeSelf || c != Character.Controlled) && c.TeamID == Character.Controlled.TeamID))
|
return characters.FindAll(c => Character.Controlled == null || ((includeSelf || c != Character.Controlled) && c.TeamID == Character.Controlled.TeamID))
|
||||||
|
// 1. Prioritize those who are already ordered to operate the item target of the new 'operate' order
|
||||||
.OrderByDescending(c => c.CurrentOrder != null && order.Category == OrderCategory.Operate && c.CurrentOrder.Identifier == order.Identifier && c.CurrentOrder.TargetEntity == order.TargetEntity)
|
.OrderByDescending(c => c.CurrentOrder != null && order.Category == OrderCategory.Operate && c.CurrentOrder.Identifier == order.Identifier && c.CurrentOrder.TargetEntity == order.TargetEntity)
|
||||||
|
// 2. Prioritize those who are currently dismissed
|
||||||
.ThenByDescending(c => c.CurrentOrder == null || c.CurrentOrder.Identifier == dismissedOrderPrefab.Identifier)
|
.ThenByDescending(c => c.CurrentOrder == null || c.CurrentOrder.Identifier == dismissedOrderPrefab.Identifier)
|
||||||
|
// 3. Prioritize those who are not currently assigned with the same type of order (for example, when giving a 'Fix Leak' order, prioritize those who have a different order)
|
||||||
.ThenBy(c => c.CurrentOrder != null && c.CurrentOrder.Identifier == order.Identifier && c.CurrentOrder.TargetEntity == order.TargetEntity)
|
.ThenBy(c => c.CurrentOrder != null && c.CurrentOrder.Identifier == order.Identifier && c.CurrentOrder.TargetEntity == order.TargetEntity)
|
||||||
|
// 4. Prioritize those with the appropriate job for the order
|
||||||
.ThenByDescending(c => order.HasAppropriateJob(c))
|
.ThenByDescending(c => order.HasAppropriateJob(c))
|
||||||
|
// 5. Prioritize those with the lowest "weight" of the current order
|
||||||
.ThenBy(c => c.CurrentOrder?.Weight)
|
.ThenBy(c => c.CurrentOrder?.Weight)
|
||||||
|
// 6. Prioritize those with the best skill for the order
|
||||||
.ThenByDescending(c => c.GetSkillLevel(order.AppropriateSkill));
|
.ThenByDescending(c => c.GetSkillLevel(order.AppropriateSkill));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3013,40 +2967,7 @@ namespace Barotrauma
|
|||||||
public void InitSinglePlayerRound()
|
public void InitSinglePlayerRound()
|
||||||
{
|
{
|
||||||
crewList.ClearChildren();
|
crewList.ClearChildren();
|
||||||
characters.Clear();
|
InitRound();
|
||||||
|
|
||||||
WayPoint[] waypoints = WayPoint.SelectCrewSpawnPoints(characterInfos, Submarine.MainSub);
|
|
||||||
|
|
||||||
for (int i = 0; i < waypoints.Length; i++)
|
|
||||||
{
|
|
||||||
Character character;
|
|
||||||
character = Character.Create(characterInfos[i], waypoints[i].WorldPosition, characterInfos[i].Name);
|
|
||||||
|
|
||||||
if (character.Info != null)
|
|
||||||
{
|
|
||||||
if (!character.Info.StartItemsGiven && character.Info.InventoryData != null)
|
|
||||||
{
|
|
||||||
DebugConsole.ThrowError($"Error when initializing a single player round: character \"{character.Name}\" has not been given their initial items but has saved inventory data. Using the saved inventory data instead of giving the character new items.");
|
|
||||||
}
|
|
||||||
if (character.Info.InventoryData != null)
|
|
||||||
{
|
|
||||||
character.Info.SpawnInventoryItems(character.Inventory, character.Info.InventoryData);
|
|
||||||
}
|
|
||||||
else if (!character.Info.StartItemsGiven)
|
|
||||||
{
|
|
||||||
character.GiveJobItems(waypoints[i]);
|
|
||||||
}
|
|
||||||
character.Info.StartItemsGiven = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
AddCharacter(character);
|
|
||||||
if (i == 0)
|
|
||||||
{
|
|
||||||
Character.Controlled = character;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
conversationTimer = Rand.Range(5.0f, 10.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EndRound()
|
public void EndRound()
|
||||||
@@ -3072,10 +2993,9 @@ namespace Barotrauma
|
|||||||
foreach (CharacterInfo ci in characterInfos)
|
foreach (CharacterInfo ci in characterInfos)
|
||||||
{
|
{
|
||||||
var infoElement = ci.Save(element);
|
var infoElement = ci.Save(element);
|
||||||
if (ci.InventoryData != null)
|
if (ci.InventoryData != null) { infoElement.Add(ci.InventoryData); }
|
||||||
{
|
if (ci.HealthData != null) { infoElement.Add(ci.HealthData); }
|
||||||
infoElement.Add(ci.InventoryData);
|
if (ci.LastControlled) { infoElement.Add(new XAttribute("lastcontrolled", true)); }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
parentElement.Add(element);
|
parentElement.Add(element);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,65 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using Barotrauma.Extensions;
|
||||||
using Barotrauma.Networking;
|
using Barotrauma.Networking;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
abstract partial class CampaignMode : GameMode
|
abstract partial class CampaignMode : GameMode
|
||||||
{
|
{
|
||||||
|
protected bool crewDead;
|
||||||
|
|
||||||
|
protected Color overlayColor;
|
||||||
|
protected string overlayText, overlayTextBottom;
|
||||||
|
protected Color overlayTextColor;
|
||||||
|
protected Sprite overlaySprite;
|
||||||
|
|
||||||
|
protected GUIButton endRoundButton;
|
||||||
|
|
||||||
|
public GUIButton EndRoundButton => endRoundButton;
|
||||||
|
|
||||||
|
protected GUIFrame campaignUIContainer;
|
||||||
|
public CampaignUI CampaignUI;
|
||||||
|
|
||||||
|
public bool ForceMapUI
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
protected set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Paused
|
||||||
|
{
|
||||||
|
get { return ForceMapUI || CoroutineManager.IsCoroutineRunning("LevelTransition"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool showCampaignUI;
|
||||||
|
private bool wasChatBoxOpen;
|
||||||
|
public bool ShowCampaignUI
|
||||||
|
{
|
||||||
|
get { return showCampaignUI; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == showCampaignUI) { return; }
|
||||||
|
var chatBox = CrewManager?.ChatBox ?? GameMain.Client?.ChatBox;
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
if (chatBox != null)
|
||||||
|
{
|
||||||
|
wasChatBoxOpen = chatBox.ToggleOpen;
|
||||||
|
chatBox.ToggleOpen = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (chatBox != null)
|
||||||
|
{
|
||||||
|
chatBox.ToggleOpen = wasChatBoxOpen;
|
||||||
|
}
|
||||||
|
showCampaignUI = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void ShowStartMessage()
|
public override void ShowStartMessage()
|
||||||
{
|
{
|
||||||
if (Mission == null) return;
|
if (Mission == null) return;
|
||||||
@@ -15,5 +70,216 @@ namespace Barotrauma
|
|||||||
UserData = "missionstartmessage"
|
UserData = "missionstartmessage"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <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()
|
||||||
|
{
|
||||||
|
//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.ManageCampaign) ||
|
||||||
|
GameMain.Client.ConnectedClients.Count == 1 ||
|
||||||
|
GameMain.Client.IsServerOwner ||
|
||||||
|
GameMain.Client.ConnectedClients.None(c =>
|
||||||
|
c.InGame && (c.IsOwner || c.HasPermission(ClientPermissions.ManageCampaign)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw(SpriteBatch spriteBatch)
|
||||||
|
{
|
||||||
|
if (overlayColor.A > 0)
|
||||||
|
{
|
||||||
|
if (overlaySprite != null)
|
||||||
|
{
|
||||||
|
GUI.DrawRectangle(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.Black * (overlayColor.A / 255.0f), isFilled: true);
|
||||||
|
float scale = Math.Max(GameMain.GraphicsWidth / overlaySprite.size.X, GameMain.GraphicsHeight / overlaySprite.size.Y);
|
||||||
|
overlaySprite.Draw(spriteBatch, new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight) / 2, overlayColor, overlaySprite.size / 2, scale: scale);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GUI.DrawRectangle(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), overlayColor, isFilled: true);
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(overlayText) && overlayTextColor.A > 0)
|
||||||
|
{
|
||||||
|
var backgroundSprite = GUI.Style.GetComponentStyle("CommandBackground").GetDefaultSprite();
|
||||||
|
Vector2 centerPos = new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight) / 2;
|
||||||
|
backgroundSprite.Draw(spriteBatch,
|
||||||
|
centerPos,
|
||||||
|
Color.White * (overlayTextColor.A / 255.0f),
|
||||||
|
origin: backgroundSprite.size / 2,
|
||||||
|
rotate: 0.0f,
|
||||||
|
scale: new Vector2(1.5f, 0.7f) * (GameMain.GraphicsWidth / 3 / backgroundSprite.size.X));
|
||||||
|
|
||||||
|
string wrappedText = ToolBox.WrapText(overlayText, GameMain.GraphicsWidth / 3, GUI.Font);
|
||||||
|
Vector2 textSize = GUI.Font.MeasureString(wrappedText);
|
||||||
|
Vector2 textPos = centerPos - textSize / 2;
|
||||||
|
GUI.DrawString(spriteBatch, textPos + Vector2.One, wrappedText, Color.Black * (overlayTextColor.A / 255.0f));
|
||||||
|
GUI.DrawString(spriteBatch, textPos, wrappedText, overlayTextColor);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(overlayTextBottom))
|
||||||
|
{
|
||||||
|
Vector2 bottomTextPos = centerPos + new Vector2(0.0f, textSize.Y + 30 * 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUI.DisableHUD || GUI.DisableUpperHUD || ForceMapUI || CoroutineManager.IsCoroutineRunning("LevelTransition"))
|
||||||
|
{
|
||||||
|
endRoundButton.Visible = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Submarine.MainSub == null) { return; }
|
||||||
|
|
||||||
|
endRoundButton.Visible = false;
|
||||||
|
var availableTransition = GetAvailableTransition(out _, out Submarine leavingSub);
|
||||||
|
string buttonText = "";
|
||||||
|
switch (availableTransition)
|
||||||
|
{
|
||||||
|
case TransitionType.ProgressToNextLocation:
|
||||||
|
case TransitionType.ProgressToNextEmptyLocation:
|
||||||
|
if (Level.Loaded.EndOutpost == null || !Level.Loaded.EndOutpost.DockedTo.Contains(leavingSub))
|
||||||
|
{
|
||||||
|
buttonText = TextManager.GetWithVariable("EnterLocation", "[locationname]", Level.Loaded.EndLocation?.Name ?? "[ERROR]");
|
||||||
|
endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TransitionType.LeaveLocation:
|
||||||
|
// not sure why this can happen at an outpost but it apparently can in multiplayer
|
||||||
|
buttonText = TextManager.GetWithVariable("LeaveLocation", "[locationname]", Level.Loaded.StartLocation?.Name ?? "[ERROR]");
|
||||||
|
endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI;
|
||||||
|
break;
|
||||||
|
case TransitionType.ReturnToPreviousLocation:
|
||||||
|
case TransitionType.ReturnToPreviousEmptyLocation:
|
||||||
|
if (Level.Loaded.StartOutpost == null || !Level.Loaded.StartOutpost.DockedTo.Contains(leavingSub))
|
||||||
|
{
|
||||||
|
buttonText = TextManager.GetWithVariable("EnterLocation", "[locationname]", Level.Loaded.StartLocation?.Name ?? "[ERROR]");
|
||||||
|
endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
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)))
|
||||||
|
{
|
||||||
|
buttonText = TextManager.GetWithVariable("LeaveLocation", "[locationname]", Level.Loaded.StartLocation?.Name ?? "[ERROR]");
|
||||||
|
endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
endRoundButton.Visible = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endRoundButton.Visible)
|
||||||
|
{
|
||||||
|
endRoundButton.Text = ToolBox.LimitString(buttonText, endRoundButton.Font, endRoundButton.Rect.Width - 5);
|
||||||
|
if (endRoundButton.Text != buttonText)
|
||||||
|
{
|
||||||
|
endRoundButton.ToolTip = buttonText;
|
||||||
|
}
|
||||||
|
endRoundButton.Enabled = AllowedToEndRound();
|
||||||
|
}
|
||||||
|
|
||||||
|
endRoundButton.DrawManually(spriteBatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task SelectSummaryScreen(RoundSummary roundSummary, LevelData newLevel, bool mirror, Action action)
|
||||||
|
{
|
||||||
|
var roundSummaryScreen = RoundSummaryScreen.Select(overlaySprite, roundSummary);
|
||||||
|
|
||||||
|
GUI.ClearCursorWait();
|
||||||
|
|
||||||
|
var loadTask = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await Task.Yield();
|
||||||
|
Rand.ThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
|
||||||
|
GameMain.GameSession.StartRound(newLevel, mirrorLevel: mirror);
|
||||||
|
Rand.ThreadId = 0;
|
||||||
|
});
|
||||||
|
TaskPool.Add("AsyncCampaignStartRound", loadTask, (t) =>
|
||||||
|
{
|
||||||
|
overlayColor = Color.Transparent;
|
||||||
|
action?.Invoke();
|
||||||
|
});
|
||||||
|
|
||||||
|
return loadTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
partial void NPCInteractProjSpecific(Character npc, Character interactor)
|
||||||
|
{
|
||||||
|
if (npc == null || interactor == null) { return; }
|
||||||
|
|
||||||
|
switch (npc.CampaignInteractionType)
|
||||||
|
{
|
||||||
|
case InteractionType.None:
|
||||||
|
case InteractionType.Talk:
|
||||||
|
return;
|
||||||
|
case InteractionType.Upgrade when !UpgradeManager.CanUpgradeSub():
|
||||||
|
UpgradeManager.CreateUpgradeErrorMessage(TextManager.Get("Dialog.CantUpgrade"), IsSinglePlayer, npc);
|
||||||
|
return;
|
||||||
|
case InteractionType.Crew when GameMain.NetworkMember != null:
|
||||||
|
CampaignUI.CrewManagement.SendCrewState(false);
|
||||||
|
goto default;
|
||||||
|
default:
|
||||||
|
ShowCampaignUI = true;
|
||||||
|
CampaignUI.SelectTab(npc.CampaignInteractionType);
|
||||||
|
CampaignUI.UpgradeStore?.RefreshAll();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void AddToGUIUpdateList()
|
||||||
|
{
|
||||||
|
if (ShowCampaignUI || ForceMapUI)
|
||||||
|
{
|
||||||
|
campaignUIContainer?.AddToGUIUpdateList();
|
||||||
|
if (CampaignUI?.UpgradeStore?.HoveredItem != null)
|
||||||
|
{
|
||||||
|
if (CampaignUI.SelectedTab != InteractionType.Upgrade) { return; }
|
||||||
|
CampaignUI?.UpgradeStore?.ItemInfoFrame.AddToGUIUpdateList(order: 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base.AddToGUIUpdateList();
|
||||||
|
CrewManager.AddToGUIUpdateList();
|
||||||
|
endRoundButton.AddToGUIUpdateList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(float deltaTime)
|
||||||
|
{
|
||||||
|
base.Update(deltaTime);
|
||||||
|
|
||||||
|
if (PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape))
|
||||||
|
{
|
||||||
|
GUIMessageBox.MessageBoxes.RemoveAll(mb => mb.UserData is RoundSummary);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ShowCampaignUI || ForceMapUI)
|
||||||
|
{
|
||||||
|
CampaignUI?.Update(deltaTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+114
@@ -0,0 +1,114 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
internal partial class CampaignMetadata
|
||||||
|
{
|
||||||
|
private const int MaxDrawnElements = 12;
|
||||||
|
|
||||||
|
public void DebugDraw(SpriteBatch spriteBatch, Vector2 pos, int debugDrawMetadataOffset, string[] ignoredMetadataInfo)
|
||||||
|
{
|
||||||
|
var campaignData = data;
|
||||||
|
foreach (string ignored in ignoredMetadataInfo)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(ignored))
|
||||||
|
{
|
||||||
|
campaignData = campaignData.Where(pair => !pair.Key.StartsWith(ignored)).ToDictionary(i => i.Key, i => i.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int offset = 0;;
|
||||||
|
if (campaignData.Count > 0)
|
||||||
|
{
|
||||||
|
offset = debugDrawMetadataOffset % campaignData.Count;
|
||||||
|
if (offset < 0) { offset += campaignData.Count; }
|
||||||
|
}
|
||||||
|
|
||||||
|
var text = "Campaign metadata:\n";
|
||||||
|
|
||||||
|
int max = 0;
|
||||||
|
for (int i = offset; i < campaignData.Count + offset; i++)
|
||||||
|
{
|
||||||
|
int index = i;
|
||||||
|
if (index >= campaignData.Count) { index -= campaignData.Count; }
|
||||||
|
|
||||||
|
var (key, value) = campaignData.ElementAt(index);
|
||||||
|
|
||||||
|
if (max < MaxDrawnElements)
|
||||||
|
{
|
||||||
|
text += $"{key.ColorizeObject()}: {value.ColorizeObject()}\n";
|
||||||
|
max++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
text += "Use arrow keys to scroll";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
text = text.TrimEnd('\n');
|
||||||
|
|
||||||
|
List<RichTextData> richTextDatas = RichTextData.GetRichTextData(text, out text) ?? new List<RichTextData>();
|
||||||
|
|
||||||
|
Vector2 size = GUI.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())
|
||||||
|
{
|
||||||
|
GUI.DrawStringWithColors(spriteBatch, infoPos, text, Color.White, richTextDatas, font: GUI.SmallFont);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GUI.DrawString(spriteBatch, infoPos, text, Color.White, font: GUI.SmallFont);
|
||||||
|
}
|
||||||
|
|
||||||
|
float y = infoRect.Bottom + 16;
|
||||||
|
if (Campaign.Factions != null)
|
||||||
|
{
|
||||||
|
const string factionHeader = "Reputations";
|
||||||
|
Vector2 factionHeaderSize = GUI.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);
|
||||||
|
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);
|
||||||
|
y += nameSize.Y + 5;
|
||||||
|
|
||||||
|
Color color = ToolBox.GradientLerp(faction.Reputation.NormalizedValue, Color.Red, Color.Yellow, Color.LightGreen);
|
||||||
|
GUI.DrawRectangle(spriteBatch, new Rectangle(GameMain.GraphicsWidth - 264, (int) y, (int)(faction.Reputation.NormalizedValue * 255), 10), color, isFilled: true);
|
||||||
|
GUI.DrawRectangle(spriteBatch, new Rectangle(GameMain.GraphicsWidth - 264, (int) y, 256, 10), Color.White);
|
||||||
|
y += 15;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Location location = Campaign.Map?.CurrentLocation;
|
||||||
|
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);
|
||||||
|
y += nameSize.Y + 5;
|
||||||
|
|
||||||
|
float normalizedReputation = MathUtils.InverseLerp(location.Reputation.MinReputation, location.Reputation.MaxReputation, location.Reputation.Value);
|
||||||
|
Color color = ToolBox.GradientLerp(normalizedReputation, Color.Red, Color.Yellow, Color.LightGreen);
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+601
-66
@@ -1,7 +1,9 @@
|
|||||||
using Barotrauma.Networking;
|
using Barotrauma.Extensions;
|
||||||
|
using Barotrauma.Networking;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
|
||||||
@@ -11,14 +13,30 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
public bool SuppressStateSending = false;
|
public bool SuppressStateSending = false;
|
||||||
|
|
||||||
private UInt16 startWatchmanID, endWatchmanID;
|
private UInt16 pendingSaveID = 1;
|
||||||
|
public UInt16 PendingSaveID
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return pendingSaveID;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
pendingSaveID = value;
|
||||||
|
//pending save ID 0 means "no save received yet"
|
||||||
|
//save IDs are always above 0, so we should never be waiting for 0
|
||||||
|
if (pendingSaveID == 0) { pendingSaveID++; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void StartCampaignSetup(IEnumerable<string> saveFiles)
|
public static void StartCampaignSetup(IEnumerable<string> saveFiles)
|
||||||
{
|
{
|
||||||
var parent = GameMain.NetLobbyScreen.CampaignSetupFrame;
|
var parent = GameMain.NetLobbyScreen.CampaignSetupFrame;
|
||||||
parent.ClearChildren();
|
parent.ClearChildren();
|
||||||
parent.Visible = true;
|
parent.Visible = true;
|
||||||
GameMain.NetLobbyScreen.HighlightMode(2);
|
GameMain.NetLobbyScreen.HighlightMode(
|
||||||
|
GameMain.NetLobbyScreen.ModeList.Content.GetChildIndex(GameMain.NetLobbyScreen.ModeList.Content.GetChildByUserData(GameModePreset.MultiPlayerCampaign)));
|
||||||
|
|
||||||
var layout = new GUILayoutGroup(new RectTransform(Vector2.One, parent.RectTransform, Anchor.Center))
|
var layout = new GUILayoutGroup(new RectTransform(Vector2.One, parent.RectTransform, Anchor.Center))
|
||||||
{
|
{
|
||||||
@@ -38,7 +56,7 @@ namespace Barotrauma
|
|||||||
var newCampaignContainer = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.95f), campaignContainer.RectTransform, Anchor.Center), style: null);
|
var newCampaignContainer = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.95f), campaignContainer.RectTransform, Anchor.Center), style: null);
|
||||||
var loadCampaignContainer = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.95f), campaignContainer.RectTransform, Anchor.Center), style: null);
|
var loadCampaignContainer = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.95f), campaignContainer.RectTransform, Anchor.Center), style: null);
|
||||||
|
|
||||||
var campaignSetupUI = new CampaignSetupUI(true, newCampaignContainer, loadCampaignContainer, null, saveFiles);
|
GameMain.NetLobbyScreen.CampaignSetupUI = new CampaignSetupUI(true, newCampaignContainer, loadCampaignContainer, null, saveFiles);
|
||||||
|
|
||||||
var newCampaignButton = new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), buttonContainer.RectTransform),
|
var newCampaignButton = new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), buttonContainer.RectTransform),
|
||||||
TextManager.Get("NewCampaign"), style: "GUITabButton")
|
TextManager.Get("NewCampaign"), style: "GUITabButton")
|
||||||
@@ -69,93 +87,487 @@ namespace Barotrauma
|
|||||||
|
|
||||||
GUITextBlock.AutoScaleAndNormalize(newCampaignButton.TextBlock, loadCampaignButton.TextBlock);
|
GUITextBlock.AutoScaleAndNormalize(newCampaignButton.TextBlock, loadCampaignButton.TextBlock);
|
||||||
|
|
||||||
campaignSetupUI.StartNewGame = GameMain.Client.SetupNewCampaign;
|
GameMain.NetLobbyScreen.CampaignSetupUI.StartNewGame = GameMain.Client.SetupNewCampaign;
|
||||||
campaignSetupUI.LoadGame = GameMain.Client.SetupLoadCampaign;
|
GameMain.NetLobbyScreen.CampaignSetupUI.LoadGame = GameMain.Client.SetupLoadCampaign;
|
||||||
|
}
|
||||||
|
|
||||||
|
partial void InitProjSpecific()
|
||||||
|
{
|
||||||
|
var buttonContainer = new GUILayoutGroup(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.ButtonAreaTop, GUICanvas.Instance),
|
||||||
|
isHorizontal: true, childAnchor: Anchor.CenterRight)
|
||||||
|
{
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
|
||||||
|
int buttonHeight = (int)(GUI.Scale * 40);
|
||||||
|
int buttonWidth = GUI.IntScale(200);
|
||||||
|
|
||||||
|
endRoundButton = new GUIButton(HUDLayoutSettings.ToRectTransform(new Rectangle((GameMain.GraphicsWidth / 2) - (buttonWidth / 2), HUDLayoutSettings.ButtonAreaTop.Center.Y - (buttonHeight / 2), buttonWidth, buttonHeight), GUICanvas.Instance),
|
||||||
|
TextManager.Get("EndRound"), textAlignment: Alignment.Center, style: "EndRoundButton")
|
||||||
|
{
|
||||||
|
Pulse = true,
|
||||||
|
TextBlock =
|
||||||
|
{
|
||||||
|
Shadow = true,
|
||||||
|
AutoScaleHorizontal = true
|
||||||
|
},
|
||||||
|
OnClicked = (btn, userdata) =>
|
||||||
|
{
|
||||||
|
var availableTransition = GetAvailableTransition(out _, out _);
|
||||||
|
if (Character.Controlled != null &&
|
||||||
|
availableTransition == TransitionType.ReturnToPreviousLocation &&
|
||||||
|
Character.Controlled?.Submarine == Level.Loaded?.StartOutpost)
|
||||||
|
{
|
||||||
|
GameMain.Client.RequestStartRound();
|
||||||
|
}
|
||||||
|
else if (Character.Controlled != null &&
|
||||||
|
availableTransition == TransitionType.ProgressToNextLocation &&
|
||||||
|
Character.Controlled?.Submarine == Level.Loaded?.EndOutpost)
|
||||||
|
{
|
||||||
|
GameMain.Client.RequestStartRound();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ShowCampaignUI = true;
|
||||||
|
if (CampaignUI == null) { InitCampaignUI(); }
|
||||||
|
CampaignUI.SelectTab(InteractionType.Map);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
buttonContainer.Recalculate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitCampaignUI()
|
||||||
|
{
|
||||||
|
campaignUIContainer = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: "InnerGlow", color: Color.Black);
|
||||||
|
CampaignUI = new CampaignUI(this, campaignUIContainer)
|
||||||
|
{
|
||||||
|
StartRound = () =>
|
||||||
|
{
|
||||||
|
GameMain.Client.RequestStartRound();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Start()
|
||||||
|
{
|
||||||
|
base.Start();
|
||||||
|
CoroutineManager.StartCoroutine(DoInitialCameraTransition(), "MultiplayerCampaign.DoInitialCameraTransition");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadInitialLevel()
|
||||||
|
{
|
||||||
|
//clients should never call this
|
||||||
|
throw new InvalidOperationException("");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private IEnumerable<object> DoInitialCameraTransition()
|
||||||
|
{
|
||||||
|
while (GameMain.Instance.LoadingScreenOpen)
|
||||||
|
{
|
||||||
|
yield return CoroutineStatus.Running;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GameMain.Client.LateCampaignJoin)
|
||||||
|
{
|
||||||
|
GameMain.Client.LateCampaignJoin = false;
|
||||||
|
yield return CoroutineStatus.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
Character prevControlled = Character.Controlled;
|
||||||
|
if (prevControlled?.AIController != null)
|
||||||
|
{
|
||||||
|
prevControlled.AIController.Enabled = false;
|
||||||
|
}
|
||||||
|
GUI.DisableHUD = true;
|
||||||
|
if (IsFirstRound)
|
||||||
|
{
|
||||||
|
Character.Controlled = null;
|
||||||
|
|
||||||
|
if (prevControlled != null)
|
||||||
|
{
|
||||||
|
prevControlled.ClearInputs();
|
||||||
|
}
|
||||||
|
|
||||||
|
overlayColor = Color.LightGray;
|
||||||
|
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) });
|
||||||
|
float fadeInDuration = 1.0f;
|
||||||
|
float textDuration = 10.0f;
|
||||||
|
float timer = 0.0f;
|
||||||
|
while (timer < textDuration)
|
||||||
|
{
|
||||||
|
// Try to grab the controlled here to prevent inputs, assigned late on multiplayer
|
||||||
|
if (Character.Controlled != null)
|
||||||
|
{
|
||||||
|
prevControlled = Character.Controlled;
|
||||||
|
Character.Controlled = null;
|
||||||
|
prevControlled.ClearInputs();
|
||||||
|
}
|
||||||
|
overlayTextColor = Color.Lerp(Color.Transparent, Color.White, (timer - 1.0f) / fadeInDuration);
|
||||||
|
timer = Math.Min(timer + CoroutineManager.DeltaTime, textDuration);
|
||||||
|
yield return CoroutineStatus.Running;
|
||||||
|
}
|
||||||
|
var transition = new CameraTransition(prevControlled, GameMain.GameScreen.Cam,
|
||||||
|
null, null,
|
||||||
|
fadeOut: false,
|
||||||
|
duration: 5,
|
||||||
|
startZoom: 1.5f, endZoom: 1.0f)
|
||||||
|
{
|
||||||
|
AllowInterrupt = true,
|
||||||
|
RemoveControlFromCharacter = false
|
||||||
|
};
|
||||||
|
fadeInDuration = 1.0f;
|
||||||
|
timer = 0.0f;
|
||||||
|
overlayTextColor = Color.Transparent;
|
||||||
|
overlayText = "";
|
||||||
|
while (timer < fadeInDuration)
|
||||||
|
{
|
||||||
|
overlayColor = Color.Lerp(Color.LightGray, Color.Transparent, timer / fadeInDuration);
|
||||||
|
timer += CoroutineManager.DeltaTime;
|
||||||
|
yield return CoroutineStatus.Running;
|
||||||
|
}
|
||||||
|
overlayColor = Color.Transparent;
|
||||||
|
while (transition.Running)
|
||||||
|
{
|
||||||
|
yield return CoroutineStatus.Running;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevControlled != null)
|
||||||
|
{
|
||||||
|
Character.Controlled = prevControlled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var transition = new CameraTransition(Submarine.MainSub, GameMain.GameScreen.Cam,
|
||||||
|
null, null,
|
||||||
|
fadeOut: false,
|
||||||
|
duration: 5,
|
||||||
|
startZoom: 0.5f, endZoom: 1.0f)
|
||||||
|
{
|
||||||
|
AllowInterrupt = true,
|
||||||
|
RemoveControlFromCharacter = true
|
||||||
|
};
|
||||||
|
while (transition.Running)
|
||||||
|
{
|
||||||
|
yield return CoroutineStatus.Running;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevControlled != null)
|
||||||
|
{
|
||||||
|
prevControlled.SelectedConstruction = null;
|
||||||
|
if (prevControlled.AIController != null)
|
||||||
|
{
|
||||||
|
prevControlled.AIController.Enabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GUI.DisableHUD = false;
|
||||||
|
yield return CoroutineStatus.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override IEnumerable<object> DoLevelTransition(TransitionType transitionType, LevelData newLevel, Submarine leavingSub, bool mirror, List<TraitorMissionResult> traitorResults = null)
|
||||||
|
{
|
||||||
|
yield return CoroutineStatus.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<object> DoLevelTransition()
|
||||||
|
{
|
||||||
|
SoundPlayer.OverrideMusicType = CrewManager.GetCharacters().Any(c => !c.IsDead) ? "endround" : "crewdead";
|
||||||
|
SoundPlayer.OverrideMusicDuration = 18.0f;
|
||||||
|
|
||||||
|
Level prevLevel = Level.Loaded;
|
||||||
|
|
||||||
|
bool success = CrewManager.GetCharacters().Any(c => !c.IsDead);
|
||||||
|
crewDead = false;
|
||||||
|
|
||||||
|
var continueButton = GameMain.GameSession.RoundSummary?.ContinueButton;
|
||||||
|
if (continueButton != null)
|
||||||
|
{
|
||||||
|
continueButton.Visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Character.Controlled = null;
|
||||||
|
|
||||||
|
yield return new WaitForSeconds(0.1f);
|
||||||
|
|
||||||
|
GameMain.Client.EndCinematic?.Stop();
|
||||||
|
var endTransition = new CameraTransition(Submarine.MainSub, GameMain.GameScreen.Cam, null,
|
||||||
|
Alignment.Center,
|
||||||
|
fadeOut: false,
|
||||||
|
duration: EndTransitionDuration);
|
||||||
|
GameMain.Client.EndCinematic = endTransition;
|
||||||
|
|
||||||
|
Location portraitLocation = Map?.SelectedLocation ?? Map?.CurrentLocation ?? Level.Loaded?.StartLocation;
|
||||||
|
if (portraitLocation != null)
|
||||||
|
{
|
||||||
|
overlaySprite = portraitLocation.Type.GetPortrait(portraitLocation.PortraitId);
|
||||||
|
}
|
||||||
|
float fadeOutDuration = endTransition.Duration;
|
||||||
|
float t = 0.0f;
|
||||||
|
while (t < fadeOutDuration || endTransition.Running)
|
||||||
|
{
|
||||||
|
t += CoroutineManager.UnscaledDeltaTime;
|
||||||
|
overlayColor = Color.Lerp(Color.Transparent, Color.White, t / fadeOutDuration);
|
||||||
|
yield return CoroutineStatus.Running;
|
||||||
|
}
|
||||||
|
overlayColor = Color.White;
|
||||||
|
yield return CoroutineStatus.Running;
|
||||||
|
|
||||||
|
//--------------------------------------
|
||||||
|
|
||||||
|
//wait for the new level to be loaded
|
||||||
|
DateTime timeOut = DateTime.Now + new TimeSpan(0, 0, seconds: 30);
|
||||||
|
while (Level.Loaded == prevLevel || Level.Loaded == null)
|
||||||
|
{
|
||||||
|
if (DateTime.Now > timeOut || Screen.Selected != GameMain.GameScreen) { break; }
|
||||||
|
yield return CoroutineStatus.Running;
|
||||||
|
}
|
||||||
|
|
||||||
|
endTransition.Stop();
|
||||||
|
overlayColor = Color.Transparent;
|
||||||
|
|
||||||
|
if (DateTime.Now > timeOut) { GameMain.NetLobbyScreen.Select(); }
|
||||||
|
if (!(Screen.Selected is RoundSummaryScreen))
|
||||||
|
{
|
||||||
|
if (continueButton != null)
|
||||||
|
{
|
||||||
|
continueButton.Visible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return CoroutineStatus.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update(float deltaTime)
|
public override void Update(float deltaTime)
|
||||||
{
|
{
|
||||||
|
if (CoroutineManager.IsCoroutineRunning("LevelTransition") || Level.Loaded == null) { return; }
|
||||||
|
|
||||||
|
if (ShowCampaignUI || ForceMapUI)
|
||||||
|
{
|
||||||
|
if (CampaignUI == null) { InitCampaignUI(); }
|
||||||
|
Character.DisableControls = true;
|
||||||
|
}
|
||||||
|
|
||||||
base.Update(deltaTime);
|
base.Update(deltaTime);
|
||||||
|
|
||||||
if (startWatchmanID > 0 && startWatchman == null)
|
if (PlayerInput.RightButtonClicked() ||
|
||||||
|
PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape))
|
||||||
{
|
{
|
||||||
startWatchman = Entity.FindEntityByID(startWatchmanID) as Character;
|
ShowCampaignUI = false;
|
||||||
if (startWatchman != null) { InitializeWatchman(startWatchman); }
|
if (GUIMessageBox.VisibleBox?.UserData is RoundSummary roundSummary &&
|
||||||
|
roundSummary.ContinueButton != null &&
|
||||||
|
roundSummary.ContinueButton.Visible)
|
||||||
|
{
|
||||||
|
GUIMessageBox.MessageBoxes.Remove(GUIMessageBox.VisibleBox);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (endWatchmanID > 0 && endWatchman == null)
|
|
||||||
|
if (!GUI.DisableHUD && !GUI.DisableUpperHUD)
|
||||||
{
|
{
|
||||||
endWatchman = Entity.FindEntityByID(endWatchmanID) as Character;
|
endRoundButton.UpdateManually(deltaTime);
|
||||||
if (endWatchman != null) { InitializeWatchman(endWatchman); }
|
if (CoroutineManager.IsCoroutineRunning("LevelTransition") || ForceMapUI) { return; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Level.Loaded.Type == LevelData.LevelType.Outpost)
|
||||||
|
{
|
||||||
|
if (wasDocked)
|
||||||
|
{
|
||||||
|
var connectedSubs = Submarine.MainSub.GetConnectedSubs();
|
||||||
|
bool isDocked = Level.Loaded.StartOutpost != null && connectedSubs.Contains(Level.Loaded.StartOutpost);
|
||||||
|
if (!isDocked)
|
||||||
|
{
|
||||||
|
//undocked from outpost, need to choose a destination
|
||||||
|
ForceMapUI = true;
|
||||||
|
if (CampaignUI == null) { InitCampaignUI(); }
|
||||||
|
CampaignUI.SelectTab(InteractionType.Map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//wasn't initially docked (sub doesn't have a docking port?)
|
||||||
|
// -> choose a destination when the sub is far enough from the start outpost
|
||||||
|
if (!Submarine.MainSub.AtStartPosition)
|
||||||
|
{
|
||||||
|
ForceMapUI = true;
|
||||||
|
if (CampaignUI == null) { InitCampaignUI(); }
|
||||||
|
CampaignUI.SelectTab(InteractionType.Map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CampaignUI == null) { InitCampaignUI(); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override void End(TransitionType transitionType = TransitionType.None)
|
||||||
|
{
|
||||||
|
base.End(transitionType);
|
||||||
|
ForceMapUI = ShowCampaignUI = false;
|
||||||
|
UpgradeManager.CanUpgrade = true;
|
||||||
|
|
||||||
|
// remove all event dialogue boxes
|
||||||
|
GUIMessageBox.MessageBoxes.ForEachMod(mb =>
|
||||||
|
{
|
||||||
|
if (mb is GUIMessageBox msgBox)
|
||||||
|
{
|
||||||
|
if (mb.UserData is Pair<string, ushort> pair && pair.First.Equals("conversationaction", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
msgBox.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (transitionType == TransitionType.End)
|
||||||
|
{
|
||||||
|
EndCampaign();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IsFirstRound = false;
|
||||||
|
CoroutineManager.StartCoroutine(DoLevelTransition(), "LevelTransition");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void WatchmanInteract(Character watchman, Character interactor)
|
protected override void EndCampaignProjSpecific()
|
||||||
{
|
{
|
||||||
if ((watchman.Submarine == Level.Loaded.StartOutpost && !Submarine.MainSub.AtStartPosition) ||
|
if (GUIMessageBox.VisibleBox?.UserData is RoundSummary roundSummary)
|
||||||
(watchman.Submarine == Level.Loaded.EndOutpost && !Submarine.MainSub.AtEndPosition))
|
|
||||||
{
|
{
|
||||||
return;
|
GUIMessageBox.MessageBoxes.Remove(GUIMessageBox.VisibleBox);
|
||||||
|
}
|
||||||
|
CoroutineManager.StartCoroutine(DoEndCampaignCameraTransition(), "DoEndCampaignCameraTransition");
|
||||||
|
GameMain.CampaignEndScreen.OnFinished = () =>
|
||||||
|
{
|
||||||
|
GameMain.NetLobbyScreen.Select();
|
||||||
|
if (GameMain.NetLobbyScreen.ContinueCampaignButton != null) { GameMain.NetLobbyScreen.ContinueCampaignButton.Enabled = false; }
|
||||||
|
if (GameMain.NetLobbyScreen.QuitCampaignButton != null) { GameMain.NetLobbyScreen.QuitCampaignButton.Enabled = false; }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<object> DoEndCampaignCameraTransition()
|
||||||
|
{
|
||||||
|
Character controlled = Character.Controlled;
|
||||||
|
if (controlled != null)
|
||||||
|
{
|
||||||
|
controlled.AIController.Enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GUIMessageBox.MessageBoxes.Any(mbox => mbox.UserData as string == "watchmanprompt"))
|
GUI.DisableHUD = true;
|
||||||
{
|
ISpatialEntity endObject = Level.Loaded.LevelObjectManager.GetAllObjects().FirstOrDefault(obj => obj.Prefab.SpawnPos == LevelObjectPrefab.SpawnPosType.LevelEnd);
|
||||||
return;
|
var transition = new CameraTransition(endObject ?? Submarine.MainSub, GameMain.GameScreen.Cam,
|
||||||
}
|
null, Alignment.Center,
|
||||||
|
fadeOut: true,
|
||||||
|
duration: 10,
|
||||||
|
startZoom: null, endZoom: 0.2f);
|
||||||
|
|
||||||
if (GameMain.Client != null && interactor == Character.Controlled)
|
while (transition.Running)
|
||||||
{
|
{
|
||||||
var msgBox = new GUIMessageBox("", TextManager.GetWithVariable("CampaignEnterOutpostPrompt", "[locationname]",
|
yield return CoroutineStatus.Running;
|
||||||
Submarine.MainSub.AtStartPosition ? Map.CurrentLocation.Name : Map.SelectedLocation.Name),
|
|
||||||
new string[] { TextManager.Get("Yes"), TextManager.Get("No") })
|
|
||||||
{
|
|
||||||
UserData = "watchmanprompt"
|
|
||||||
};
|
|
||||||
msgBox.Buttons[0].OnClicked = (btn, userdata) =>
|
|
||||||
{
|
|
||||||
GameMain.Client.RequestRoundEnd();
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
|
||||||
msgBox.Buttons[1].OnClicked += msgBox.Close;
|
|
||||||
}
|
}
|
||||||
|
GameMain.CampaignEndScreen.Select();
|
||||||
|
GUI.DisableHUD = false;
|
||||||
|
|
||||||
|
yield return CoroutineStatus.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg)
|
public void ClientWrite(IWriteMessage msg)
|
||||||
{
|
{
|
||||||
System.Diagnostics.Debug.Assert(map.Locations.Count < UInt16.MaxValue);
|
System.Diagnostics.Debug.Assert(map.Locations.Count < UInt16.MaxValue);
|
||||||
|
|
||||||
|
msg.Write(map.CurrentLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.CurrentLocationIndex);
|
||||||
msg.Write(map.SelectedLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.SelectedLocationIndex);
|
msg.Write(map.SelectedLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.SelectedLocationIndex);
|
||||||
msg.Write(map.SelectedMissionIndex == -1 ? byte.MaxValue : (byte)map.SelectedMissionIndex);
|
msg.Write(map.SelectedMissionIndex == -1 ? byte.MaxValue : (byte)map.SelectedMissionIndex);
|
||||||
msg.Write(PurchasedHullRepairs);
|
msg.Write(PurchasedHullRepairs);
|
||||||
msg.Write(PurchasedItemRepairs);
|
msg.Write(PurchasedItemRepairs);
|
||||||
msg.Write(PurchasedLostShuttles);
|
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, 100);
|
||||||
|
}
|
||||||
|
|
||||||
msg.Write((UInt16)CargoManager.PurchasedItems.Count);
|
msg.Write((UInt16)CargoManager.PurchasedItems.Count);
|
||||||
foreach (PurchasedItem pi in CargoManager.PurchasedItems)
|
foreach (PurchasedItem pi in CargoManager.PurchasedItems)
|
||||||
{
|
{
|
||||||
msg.Write(pi.ItemPrefab.Identifier);
|
msg.Write(pi.ItemPrefab.Identifier);
|
||||||
msg.WriteRangedInteger(pi.Quantity, 0, 100);
|
msg.WriteRangedInteger(pi.Quantity, 0, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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((ushort)UpgradeManager.PurchasedUpgrades.Count);
|
||||||
|
foreach (var (prefab, category, level) in UpgradeManager.PurchasedUpgrades)
|
||||||
|
{
|
||||||
|
msg.Write(prefab.Identifier);
|
||||||
|
msg.Write(category.Identifier);
|
||||||
|
msg.Write((byte)level);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//static because we may need to instantiate the campaign if it hasn't been done yet
|
//static because we may need to instantiate the campaign if it hasn't been done yet
|
||||||
public static void ClientRead(IReadMessage msg)
|
public static void ClientRead(IReadMessage msg)
|
||||||
{
|
{
|
||||||
byte campaignID = msg.ReadByte();
|
bool isFirstRound = msg.ReadBoolean();
|
||||||
UInt16 updateID = msg.ReadUInt16();
|
byte campaignID = msg.ReadByte();
|
||||||
UInt16 saveID = msg.ReadUInt16();
|
UInt16 updateID = msg.ReadUInt16();
|
||||||
string mapSeed = msg.ReadString();
|
UInt16 saveID = msg.ReadUInt16();
|
||||||
UInt16 currentLocIndex = msg.ReadUInt16();
|
string mapSeed = msg.ReadString();
|
||||||
UInt16 selectedLocIndex = msg.ReadUInt16();
|
UInt16 currentLocIndex = msg.ReadUInt16();
|
||||||
byte selectedMissionIndex = msg.ReadByte();
|
UInt16 selectedLocIndex = msg.ReadUInt16();
|
||||||
|
byte selectedMissionIndex = msg.ReadByte();
|
||||||
|
float? reputation = null;
|
||||||
|
if (msg.ReadBoolean()) { reputation = msg.ReadSingle(); }
|
||||||
|
|
||||||
UInt16 startWatchmanID = msg.ReadUInt16();
|
Dictionary<string, float> factionReps = new Dictionary<string, float>();
|
||||||
UInt16 endWatchmanID = msg.ReadUInt16();
|
byte factionsCount = msg.ReadByte();
|
||||||
|
for (int i = 0; i < factionsCount; i++)
|
||||||
|
{
|
||||||
|
factionReps.Add(msg.ReadString(), msg.ReadSingle());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool forceMapUI = msg.ReadBoolean();
|
||||||
|
|
||||||
int money = msg.ReadInt32();
|
int money = msg.ReadInt32();
|
||||||
bool purchasedHullRepairs = msg.ReadBoolean();
|
bool purchasedHullRepairs = msg.ReadBoolean();
|
||||||
bool purchasedItemRepairs = msg.ReadBoolean();
|
bool purchasedItemRepairs = msg.ReadBoolean();
|
||||||
bool purchasedLostShuttles = msg.ReadBoolean();
|
bool purchasedLostShuttles = msg.ReadBoolean();
|
||||||
|
|
||||||
|
byte missionCount = msg.ReadByte();
|
||||||
|
List<Pair<string, byte>> availableMissions = new List<Pair<string, byte>>();
|
||||||
|
for (int i = 0; i < missionCount; i++)
|
||||||
|
{
|
||||||
|
string missionIdentifier = msg.ReadString();
|
||||||
|
byte connectionIndex = msg.ReadByte();
|
||||||
|
availableMissions.Add(new Pair<string, byte>(missionIdentifier, connectionIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt16? storeBalance = null;
|
||||||
|
if (msg.ReadBoolean())
|
||||||
|
{
|
||||||
|
storeBalance = msg.ReadUInt16();
|
||||||
|
}
|
||||||
|
|
||||||
|
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 purchasedItemCount = msg.ReadUInt16();
|
UInt16 purchasedItemCount = msg.ReadUInt16();
|
||||||
List<PurchasedItem> purchasedItems = new List<PurchasedItem>();
|
List<PurchasedItem> purchasedItems = new List<PurchasedItem>();
|
||||||
@@ -166,6 +578,30 @@ namespace Barotrauma
|
|||||||
purchasedItems.Add(new PurchasedItem(ItemPrefab.Prefabs[itemPrefabIdentifier], itemQuantity));
|
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();
|
||||||
|
soldItems.Add(new SoldItem(ItemPrefab.Prefabs[itemPrefabIdentifier], id, removed, sellerId));
|
||||||
|
}
|
||||||
|
|
||||||
|
ushort pendingUpgradeCount = msg.ReadUInt16();
|
||||||
|
List<PurchasedUpgrade> pendingUpgrades = new List<PurchasedUpgrade>();
|
||||||
|
for (int i = 0; i < pendingUpgradeCount; i++)
|
||||||
|
{
|
||||||
|
string upgradeIdentifier = msg.ReadString();
|
||||||
|
UpgradePrefab prefab = UpgradePrefab.Find(upgradeIdentifier);
|
||||||
|
string categoryIdentifier = msg.ReadString();
|
||||||
|
UpgradeCategory category = UpgradeCategory.Find(categoryIdentifier);
|
||||||
|
int upgradeLevel = msg.ReadByte();
|
||||||
|
if (prefab == null || category == null) { continue; }
|
||||||
|
pendingUpgrades.Add(new PurchasedUpgrade(prefab, category, upgradeLevel));
|
||||||
|
}
|
||||||
|
|
||||||
bool hasCharacterData = msg.ReadBoolean();
|
bool hasCharacterData = msg.ReadBoolean();
|
||||||
CharacterInfo myCharacterInfo = null;
|
CharacterInfo myCharacterInfo = null;
|
||||||
if (hasCharacterData)
|
if (hasCharacterData)
|
||||||
@@ -173,58 +609,98 @@ namespace Barotrauma
|
|||||||
myCharacterInfo = CharacterInfo.ClientRead(CharacterPrefab.HumanSpeciesName, msg);
|
myCharacterInfo = CharacterInfo.ClientRead(CharacterPrefab.HumanSpeciesName, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
MultiPlayerCampaign campaign = GameMain.GameSession?.GameMode as MultiPlayerCampaign;
|
if (!(GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign) || campaignID != campaign.CampaignID)
|
||||||
if (campaign == null || campaignID != campaign.CampaignID)
|
|
||||||
{
|
{
|
||||||
string savePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Multiplayer);
|
string savePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Multiplayer);
|
||||||
|
|
||||||
GameMain.GameSession = new GameSession(null, savePath,
|
GameMain.GameSession = new GameSession(null, savePath, GameModePreset.MultiPlayerCampaign, mapSeed);
|
||||||
GameModePreset.List.Find(g => g.Identifier == "multiplayercampaign"));
|
campaign = (MultiPlayerCampaign)GameMain.GameSession.GameMode;
|
||||||
|
|
||||||
campaign = ((MultiPlayerCampaign)GameMain.GameSession.GameMode);
|
|
||||||
campaign.CampaignID = campaignID;
|
campaign.CampaignID = campaignID;
|
||||||
campaign.GenerateMap(mapSeed);
|
|
||||||
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
|
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//server has a newer save file
|
//server has a newer save file
|
||||||
if (NetIdUtils.IdMoreRecent(saveID, campaign.PendingSaveID))
|
if (NetIdUtils.IdMoreRecent(saveID, campaign.PendingSaveID))
|
||||||
{
|
{
|
||||||
/*//stop any active campaign save transfers, they're outdated now
|
|
||||||
List<FileReceiver.FileTransferIn> saveTransfers =
|
|
||||||
GameMain.Client.FileReceiver.ActiveTransfers.FindAll(t => t.FileType == FileTransferType.CampaignSave);
|
|
||||||
|
|
||||||
foreach (var transfer in saveTransfers)
|
|
||||||
{
|
|
||||||
GameMain.Client.FileReceiver.StopTransfer(transfer);
|
|
||||||
}
|
|
||||||
|
|
||||||
GameMain.Client.RequestFile(FileTransferType.CampaignSave, null, null);*/
|
|
||||||
campaign.PendingSaveID = saveID;
|
campaign.PendingSaveID = saveID;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NetIdUtils.IdMoreRecent(updateID, campaign.lastUpdateID))
|
if (NetIdUtils.IdMoreRecent(updateID, campaign.lastUpdateID))
|
||||||
{
|
{
|
||||||
campaign.SuppressStateSending = true;
|
campaign.SuppressStateSending = true;
|
||||||
|
campaign.IsFirstRound = isFirstRound;
|
||||||
|
|
||||||
//we need to have the latest save file to display location/mission/store
|
//we need to have the latest save file to display location/mission/store
|
||||||
if (campaign.LastSaveID == saveID)
|
if (campaign.LastSaveID == saveID)
|
||||||
{
|
{
|
||||||
|
campaign.ForceMapUI = forceMapUI;
|
||||||
|
|
||||||
|
UpgradeStore.WaitForServerUpdate = false;
|
||||||
|
|
||||||
campaign.Map.SetLocation(currentLocIndex == UInt16.MaxValue ? -1 : currentLocIndex);
|
campaign.Map.SetLocation(currentLocIndex == UInt16.MaxValue ? -1 : currentLocIndex);
|
||||||
campaign.Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex);
|
campaign.Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex);
|
||||||
campaign.Map.SelectMission(selectedMissionIndex);
|
campaign.Map.SelectMission(selectedMissionIndex);
|
||||||
|
campaign.CargoManager.SetItemsInBuyCrate(buyCrateItems);
|
||||||
campaign.CargoManager.SetPurchasedItems(purchasedItems);
|
campaign.CargoManager.SetPurchasedItems(purchasedItems);
|
||||||
|
campaign.CargoManager.SetSoldItems(soldItems);
|
||||||
|
if (storeBalance.HasValue) { campaign.Map.CurrentLocation.StoreCurrentBalance = storeBalance.Value; }
|
||||||
|
campaign.UpgradeManager.SetPendingUpgrades(pendingUpgrades);
|
||||||
|
campaign.UpgradeManager.PurchasedUpgrades.Clear();
|
||||||
|
|
||||||
|
foreach (var (identifier, rep) in factionReps)
|
||||||
|
{
|
||||||
|
Faction faction = campaign.Factions.FirstOrDefault(f => f.Prefab.Identifier.Equals(identifier, StringComparison.OrdinalIgnoreCase));
|
||||||
|
if (faction?.Reputation != null)
|
||||||
|
{
|
||||||
|
faction.Reputation.Value = rep;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError($"Received an update for a faction that doesn't exist \"{identifier}\".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reputation.HasValue)
|
||||||
|
{
|
||||||
|
campaign.Map.CurrentLocation.Reputation.Value = reputation.Value;
|
||||||
|
campaign?.CampaignUI?.UpgradeStore?.RefreshAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var availableMission in availableMissions)
|
||||||
|
{
|
||||||
|
MissionPrefab missionPrefab = MissionPrefab.List.Find(mp => mp.Identifier == availableMission.First);
|
||||||
|
if (missionPrefab == null)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError($"Error when receiving campaign data from the server: mission prefab \"{availableMission.First}\" not found.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (availableMission.Second < 0 || availableMission.Second >= 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}).");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
LocationConnection connection = campaign.Map.CurrentLocation.Connections[availableMission.Second];
|
||||||
|
campaign.Map.CurrentLocation.UnlockMission(missionPrefab, connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
campaign.startWatchmanID = startWatchmanID;
|
bool shouldRefresh = campaign.Money != money ||
|
||||||
campaign.endWatchmanID = endWatchmanID;
|
campaign.PurchasedHullRepairs != purchasedHullRepairs ||
|
||||||
|
campaign.PurchasedItemRepairs != purchasedItemRepairs ||
|
||||||
|
campaign.PurchasedLostShuttles != purchasedLostShuttles;
|
||||||
|
|
||||||
campaign.Money = money;
|
campaign.Money = money;
|
||||||
campaign.PurchasedHullRepairs = purchasedHullRepairs;
|
campaign.PurchasedHullRepairs = purchasedHullRepairs;
|
||||||
campaign.PurchasedItemRepairs = purchasedItemRepairs;
|
campaign.PurchasedItemRepairs = purchasedItemRepairs;
|
||||||
campaign.PurchasedLostShuttles = purchasedLostShuttles;
|
campaign.PurchasedLostShuttles = purchasedLostShuttles;
|
||||||
|
|
||||||
|
if (shouldRefresh)
|
||||||
|
{
|
||||||
|
campaign?.CampaignUI?.UpgradeStore?.RefreshAll();
|
||||||
|
}
|
||||||
|
|
||||||
if (myCharacterInfo != null)
|
if (myCharacterInfo != null)
|
||||||
{
|
{
|
||||||
GameMain.Client.CharacterInfo = myCharacterInfo;
|
GameMain.Client.CharacterInfo = myCharacterInfo;
|
||||||
@@ -240,9 +716,68 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ClientReadCrew(IReadMessage msg)
|
||||||
|
{
|
||||||
|
ushort availableHireLength = msg.ReadUInt16();
|
||||||
|
List<CharacterInfo> availableHires = new List<CharacterInfo>();
|
||||||
|
for (int i = 0; i < availableHireLength; i++)
|
||||||
|
{
|
||||||
|
CharacterInfo hire = CharacterInfo.ClientRead("human", msg);
|
||||||
|
hire.Salary = msg.ReadInt32();
|
||||||
|
availableHires.Add(hire);
|
||||||
|
}
|
||||||
|
|
||||||
|
ushort pendingHireLength = msg.ReadUInt16();
|
||||||
|
List<int> pendingHires = new List<int>();
|
||||||
|
for (int i = 0; i < pendingHireLength; i++)
|
||||||
|
{
|
||||||
|
pendingHires.Add(msg.ReadInt32());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool validateHires = msg.ReadBoolean();
|
||||||
|
|
||||||
|
bool fireCharacter = msg.ReadBoolean();
|
||||||
|
|
||||||
|
int firedIdentifier = -1;
|
||||||
|
if (fireCharacter) { firedIdentifier = msg.ReadInt32(); }
|
||||||
|
|
||||||
|
if (fireCharacter)
|
||||||
|
{
|
||||||
|
CharacterInfo firedCharacter = CrewManager.CharacterInfos.FirstOrDefault(info => info.GetIdentifier() == firedIdentifier);
|
||||||
|
// this one might and is allowed to be null since the character is already fired on the original sender's game
|
||||||
|
if (firedCharacter != null) { CrewManager.FireCharacter(firedCharacter); }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (map?.CurrentLocation?.HireManager != null && CampaignUI?.CrewManagement != null)
|
||||||
|
{
|
||||||
|
CampaignUI?.CrewManagement?.SetHireables(map.CurrentLocation, availableHires);
|
||||||
|
if (validateHires) { CampaignUI?.CrewManagement.ValidatePendingHires(); }
|
||||||
|
CampaignUI?.CrewManagement?.SetPendingHires(pendingHires, map?.CurrentLocation);
|
||||||
|
if (fireCharacter) { CampaignUI?.CrewManagement.UpdateCrew(); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void Save(XElement element)
|
public override void Save(XElement element)
|
||||||
{
|
{
|
||||||
//do nothing, the clients get the save files from the server
|
//do nothing, the clients get the save files from the server
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void LoadState(string filePath)
|
||||||
|
{
|
||||||
|
DebugConsole.Log($"Loading save file for an existing game session ({filePath})");
|
||||||
|
SaveUtil.DecompressToDirectory(filePath, SaveUtil.TempPath, null);
|
||||||
|
|
||||||
|
string gamesessionDocPath = Path.Combine(SaveUtil.TempPath, "gamesession.xml");
|
||||||
|
XDocument doc = XMLExtensions.TryLoadXml(gamesessionDocPath);
|
||||||
|
if (doc == null)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError($"Failed to load the state of a multiplayer campaign. Could not open the file \"{gamesessionDocPath}\".");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Load(doc.Root.Element("MultiPlayerCampaign"));
|
||||||
|
SubmarineInfo selectedSub;
|
||||||
|
GameMain.GameSession.OwnedSubmarines = SaveUtil.LoadOwnedSubmarines(doc, out selectedSub);
|
||||||
|
GameMain.GameSession.SubmarineInfo = selectedSub;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+606
-379
File diff suppressed because it is too large
Load Diff
@@ -1,80 +0,0 @@
|
|||||||
using Barotrauma.Tutorials;
|
|
||||||
using Microsoft.Xna.Framework;
|
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Xml.Linq;
|
|
||||||
|
|
||||||
namespace Barotrauma
|
|
||||||
{
|
|
||||||
class SubTestMode : GameMode
|
|
||||||
{
|
|
||||||
public SubTestMode(GameModePreset preset, object param)
|
|
||||||
: base(preset, param)
|
|
||||||
{
|
|
||||||
foreach (JobPrefab jobPrefab in JobPrefab.Prefabs)
|
|
||||||
{
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Start()
|
|
||||||
{
|
|
||||||
base.Start();
|
|
||||||
|
|
||||||
isRunning = true;
|
|
||||||
CrewManager.InitSinglePlayerRound();
|
|
||||||
|
|
||||||
Submarine.MainSub.SetPosition(Vector2.Zero);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Draw(SpriteBatch spriteBatch)
|
|
||||||
{
|
|
||||||
if (!isRunning|| GUI.DisableHUD || GUI.DisableUpperHUD) return;
|
|
||||||
|
|
||||||
if (Submarine.MainSub == null) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void AddToGUIUpdateList()
|
|
||||||
{
|
|
||||||
if (!isRunning) return;
|
|
||||||
|
|
||||||
base.AddToGUIUpdateList();
|
|
||||||
CrewManager.AddToGUIUpdateList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Update(float deltaTime)
|
|
||||||
{
|
|
||||||
if (!isRunning) { return; }
|
|
||||||
|
|
||||||
base.Update(deltaTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void End(string endMessage = "")
|
|
||||||
{
|
|
||||||
isRunning = false;
|
|
||||||
|
|
||||||
GameMain.GameSession.EndRound("");
|
|
||||||
|
|
||||||
CrewManager.EndRound();
|
|
||||||
|
|
||||||
Submarine.Unload();
|
|
||||||
|
|
||||||
GameMain.SubEditorScreen.Select();
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool EndRound(Submarine leavingSub)
|
|
||||||
{
|
|
||||||
isRunning = false;
|
|
||||||
|
|
||||||
End("");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
class TestGameMode : GameMode
|
||||||
|
{
|
||||||
|
public Action OnRoundEnd;
|
||||||
|
|
||||||
|
public TestGameMode(GameModePreset preset) : base(preset)
|
||||||
|
{
|
||||||
|
foreach (JobPrefab jobPrefab in JobPrefab.Prefabs)
|
||||||
|
{
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Start()
|
||||||
|
{
|
||||||
|
base.Start();
|
||||||
|
|
||||||
|
CrewManager.InitSinglePlayerRound();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void End(CampaignMode.TransitionType transitionType = CampaignMode.TransitionType.None)
|
||||||
|
{
|
||||||
|
OnRoundEnd?.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -614,7 +614,7 @@ namespace Barotrauma.Tutorials
|
|||||||
GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
|
GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
|
||||||
GameMain.LightManager.LosEnabled = false;
|
GameMain.LightManager.LosEnabled = false;
|
||||||
|
|
||||||
var cinematic = new RoundEndCinematic(Submarine.MainSub, GameMain.GameScreen.Cam, 5.0f);
|
var cinematic = new CameraTransition(Submarine.MainSub, GameMain.GameScreen.Cam, Alignment.CenterLeft, Alignment.CenterRight, duration: 5.0f);
|
||||||
|
|
||||||
while (cinematic.Running)
|
while (cinematic.Running)
|
||||||
{
|
{
|
||||||
|
|||||||
+5
-1
@@ -101,6 +101,7 @@ namespace Barotrauma.Tutorials
|
|||||||
tutorial_submarineDoorLight = Item.ItemList.Find(i => i.HasTag("tutorial_submarinedoorlight")).GetComponent<LightComponent>();
|
tutorial_submarineDoorLight = Item.ItemList.Find(i => i.HasTag("tutorial_submarinedoorlight")).GetComponent<LightComponent>();
|
||||||
var medicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("medicaldoctor"));
|
var medicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("medicaldoctor"));
|
||||||
captain_medic = Character.Create(medicInfo, captain_medicSpawnPos, "medicaldoctor");
|
captain_medic = Character.Create(medicInfo, captain_medicSpawnPos, "medicaldoctor");
|
||||||
|
captain_medic.TeamID = Character.TeamType.Team1;
|
||||||
captain_medic.GiveJobItems(null);
|
captain_medic.GiveJobItems(null);
|
||||||
captain_medic.CanSpeak = captain_medic.AIController.Enabled = false;
|
captain_medic.CanSpeak = captain_medic.AIController.Enabled = false;
|
||||||
SetDoorAccess(tutorial_submarineDoor, tutorial_submarineDoorLight, false);
|
SetDoorAccess(tutorial_submarineDoor, tutorial_submarineDoorLight, false);
|
||||||
@@ -123,14 +124,17 @@ namespace Barotrauma.Tutorials
|
|||||||
|
|
||||||
var mechanicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("mechanic"));
|
var mechanicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("mechanic"));
|
||||||
captain_mechanic = Character.Create(mechanicInfo, WayPoint.GetRandom(SpawnType.Human, mechanicInfo.Job, Submarine.MainSub).WorldPosition, "mechanic");
|
captain_mechanic = Character.Create(mechanicInfo, WayPoint.GetRandom(SpawnType.Human, mechanicInfo.Job, Submarine.MainSub).WorldPosition, "mechanic");
|
||||||
|
captain_mechanic.TeamID = Character.TeamType.Team1;
|
||||||
captain_mechanic.GiveJobItems();
|
captain_mechanic.GiveJobItems();
|
||||||
|
|
||||||
var securityInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("securityofficer"));
|
var securityInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("securityofficer"));
|
||||||
captain_security = Character.Create(securityInfo, WayPoint.GetRandom(SpawnType.Human, securityInfo.Job, Submarine.MainSub).WorldPosition, "securityofficer");
|
captain_security = Character.Create(securityInfo, WayPoint.GetRandom(SpawnType.Human, securityInfo.Job, Submarine.MainSub).WorldPosition, "securityofficer");
|
||||||
|
captain_security.TeamID = Character.TeamType.Team1;
|
||||||
captain_security.GiveJobItems();
|
captain_security.GiveJobItems();
|
||||||
|
|
||||||
var engineerInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("engineer"));
|
var engineerInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("engineer"));
|
||||||
captain_engineer = Character.Create(engineerInfo, WayPoint.GetRandom(SpawnType.Human, engineerInfo.Job, Submarine.MainSub).WorldPosition, "engineer");
|
captain_engineer = Character.Create(engineerInfo, WayPoint.GetRandom(SpawnType.Human, engineerInfo.Job, Submarine.MainSub).WorldPosition, "engineer");
|
||||||
|
captain_engineer.TeamID = Character.TeamType.Team1;
|
||||||
captain_engineer.GiveJobItems();
|
captain_engineer.GiveJobItems();
|
||||||
|
|
||||||
captain_mechanic.CanSpeak = captain_security.CanSpeak = captain_engineer.CanSpeak = false;
|
captain_mechanic.CanSpeak = captain_security.CanSpeak = captain_engineer.CanSpeak = false;
|
||||||
@@ -195,7 +199,7 @@ namespace Barotrauma.Tutorials
|
|||||||
// GameMain.GameSession.CrewManager.HighlightOrderButton(captain_security, "operateweapons", highlightColor, new Vector2(5, 5));
|
// GameMain.GameSession.CrewManager.HighlightOrderButton(captain_security, "operateweapons", highlightColor, new Vector2(5, 5));
|
||||||
HighlightOrderOption("fireatwill");
|
HighlightOrderOption("fireatwill");
|
||||||
}
|
}
|
||||||
while (!HasOrder(captain_security, "operateweapons", "fireatwill"));
|
while (!HasOrder(captain_security, "operateweapons"));
|
||||||
RemoveCompletedObjective(segments[2]);
|
RemoveCompletedObjective(segments[2]);
|
||||||
yield return new WaitForSeconds(4f, false);
|
yield return new WaitForSeconds(4f, false);
|
||||||
TriggerTutorialSegment(3, GameMain.Config.KeyBindText(InputType.Command));
|
TriggerTutorialSegment(3, GameMain.Config.KeyBindText(InputType.Command));
|
||||||
|
|||||||
+5
@@ -80,6 +80,7 @@ namespace Barotrauma.Tutorials
|
|||||||
|
|
||||||
var assistantInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("assistant"));
|
var assistantInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("assistant"));
|
||||||
patient1 = Character.Create(assistantInfo, patientHull1.WorldPosition, "1");
|
patient1 = Character.Create(assistantInfo, patientHull1.WorldPosition, "1");
|
||||||
|
patient1.TeamID = Character.TeamType.Team1;
|
||||||
patient1.GiveJobItems(null);
|
patient1.GiveJobItems(null);
|
||||||
patient1.CanSpeak = false;
|
patient1.CanSpeak = false;
|
||||||
patient1.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.Burn, 45.0f) }, stun: 0, playSound: false);
|
patient1.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.Burn, 45.0f) }, stun: 0, playSound: false);
|
||||||
@@ -87,22 +88,26 @@ namespace Barotrauma.Tutorials
|
|||||||
|
|
||||||
assistantInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("assistant"));
|
assistantInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("assistant"));
|
||||||
patient2 = Character.Create(assistantInfo, patientHull2.WorldPosition, "2");
|
patient2 = Character.Create(assistantInfo, patientHull2.WorldPosition, "2");
|
||||||
|
patient2.TeamID = Character.TeamType.Team1;
|
||||||
patient2.GiveJobItems(null);
|
patient2.GiveJobItems(null);
|
||||||
patient2.CanSpeak = false;
|
patient2.CanSpeak = false;
|
||||||
patient2.AIController.Enabled = false;
|
patient2.AIController.Enabled = false;
|
||||||
|
|
||||||
var mechanicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("engineer"));
|
var mechanicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("engineer"));
|
||||||
var subPatient1 = Character.Create(mechanicInfo, WayPoint.GetRandom(SpawnType.Human, mechanicInfo.Job, Submarine.MainSub).WorldPosition, "3");
|
var subPatient1 = Character.Create(mechanicInfo, WayPoint.GetRandom(SpawnType.Human, mechanicInfo.Job, Submarine.MainSub).WorldPosition, "3");
|
||||||
|
subPatient1.TeamID = Character.TeamType.Team1;
|
||||||
subPatient1.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.Burn, 40.0f) }, stun: 0, playSound: false);
|
subPatient1.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.Burn, 40.0f) }, stun: 0, playSound: false);
|
||||||
subPatients.Add(subPatient1);
|
subPatients.Add(subPatient1);
|
||||||
|
|
||||||
var securityInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("securityofficer"));
|
var securityInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("securityofficer"));
|
||||||
var subPatient2 = Character.Create(securityInfo, WayPoint.GetRandom(SpawnType.Human, securityInfo.Job, Submarine.MainSub).WorldPosition, "3");
|
var subPatient2 = Character.Create(securityInfo, WayPoint.GetRandom(SpawnType.Human, securityInfo.Job, Submarine.MainSub).WorldPosition, "3");
|
||||||
|
subPatient2.TeamID = Character.TeamType.Team1;
|
||||||
subPatient2.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.InternalDamage, 40.0f) }, stun: 0, playSound: false);
|
subPatient2.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.InternalDamage, 40.0f) }, stun: 0, playSound: false);
|
||||||
subPatients.Add(subPatient2);
|
subPatients.Add(subPatient2);
|
||||||
|
|
||||||
var engineerInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("engineer"));
|
var engineerInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("engineer"));
|
||||||
var subPatient3 = Character.Create(securityInfo, WayPoint.GetRandom(SpawnType.Human, engineerInfo.Job, Submarine.MainSub).WorldPosition, "3");
|
var subPatient3 = Character.Create(securityInfo, WayPoint.GetRandom(SpawnType.Human, engineerInfo.Job, Submarine.MainSub).WorldPosition, "3");
|
||||||
|
subPatient3.TeamID = Character.TeamType.Team1;
|
||||||
subPatient3.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.Burn, 20.0f) }, stun: 0, playSound: false);
|
subPatient3.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.Burn, 20.0f) }, stun: 0, playSound: false);
|
||||||
subPatients.Add(subPatient3);
|
subPatients.Add(subPatient3);
|
||||||
|
|
||||||
|
|||||||
+15
-10
@@ -376,7 +376,7 @@ namespace Barotrauma.Tutorials
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
yield return null;
|
yield return null;
|
||||||
} while (!engineer_brokenJunctionBox.IsFullCondition); // Wait until repaired
|
} while (engineer_brokenJunctionBox.Condition < repairableJunctionBoxComponent.RepairThreshold); // Wait until repaired
|
||||||
SetHighlight(engineer_brokenJunctionBox, false);
|
SetHighlight(engineer_brokenJunctionBox, false);
|
||||||
RemoveCompletedObjective(segments[2]);
|
RemoveCompletedObjective(segments[2]);
|
||||||
SetDoorAccess(engineer_thirdDoor, engineer_thirdDoorLight, true);
|
SetDoorAccess(engineer_thirdDoor, engineer_thirdDoorLight, true);
|
||||||
@@ -408,15 +408,20 @@ namespace Barotrauma.Tutorials
|
|||||||
yield return new WaitForSeconds(2f, false);
|
yield return new WaitForSeconds(2f, false);
|
||||||
TriggerTutorialSegment(4); // Repair junction box
|
TriggerTutorialSegment(4); // Repair junction box
|
||||||
while (ContentRunning) yield return null;
|
while (ContentRunning) yield return null;
|
||||||
SetHighlight(engineer_submarineJunctionBox_1, true);
|
|
||||||
SetHighlight(engineer_submarineJunctionBox_2, true);
|
|
||||||
SetHighlight(engineer_submarineJunctionBox_3, true);
|
|
||||||
engineer.AddActiveObjectiveEntity(engineer_submarineJunctionBox_1, engineer_repairIcon, engineer_repairIconColor);
|
engineer.AddActiveObjectiveEntity(engineer_submarineJunctionBox_1, engineer_repairIcon, engineer_repairIconColor);
|
||||||
engineer.AddActiveObjectiveEntity(engineer_submarineJunctionBox_2, engineer_repairIcon, engineer_repairIconColor);
|
engineer.AddActiveObjectiveEntity(engineer_submarineJunctionBox_2, engineer_repairIcon, engineer_repairIconColor);
|
||||||
engineer.AddActiveObjectiveEntity(engineer_submarineJunctionBox_3, engineer_repairIcon, engineer_repairIconColor);
|
engineer.AddActiveObjectiveEntity(engineer_submarineJunctionBox_3, engineer_repairIcon, engineer_repairIconColor);
|
||||||
|
SetHighlight(engineer_submarineJunctionBox_1, true);
|
||||||
|
SetHighlight(engineer_submarineJunctionBox_2, true);
|
||||||
|
SetHighlight(engineer_submarineJunctionBox_3, true);
|
||||||
|
|
||||||
|
Repairable repairableJunctionBoxComponent1 = engineer_submarineJunctionBox_1.GetComponent<Repairable>();
|
||||||
|
Repairable repairableJunctionBoxComponent2 = engineer_submarineJunctionBox_2.GetComponent<Repairable>();
|
||||||
|
Repairable repairableJunctionBoxComponent3 = engineer_submarineJunctionBox_3.GetComponent<Repairable>();
|
||||||
|
|
||||||
// Remove highlights when each individual machine is repaired
|
// Remove highlights when each individual machine is repaired
|
||||||
do { CheckJunctionBoxHighlights(); yield return null; } while (!engineer_submarineJunctionBox_1.IsFullCondition || !engineer_submarineJunctionBox_2.IsFullCondition || !engineer_submarineJunctionBox_3.IsFullCondition);
|
do { CheckJunctionBoxHighlights(repairableJunctionBoxComponent1, repairableJunctionBoxComponent2, repairableJunctionBoxComponent3); yield return null; } while (engineer_submarineJunctionBox_1.Condition < repairableJunctionBoxComponent1.RepairThreshold || engineer_submarineJunctionBox_2.Condition < repairableJunctionBoxComponent2.RepairThreshold || engineer_submarineJunctionBox_3.Condition < repairableJunctionBoxComponent3.RepairThreshold);
|
||||||
CheckJunctionBoxHighlights();
|
CheckJunctionBoxHighlights(repairableJunctionBoxComponent1, repairableJunctionBoxComponent2, repairableJunctionBoxComponent3);
|
||||||
RemoveCompletedObjective(segments[4]);
|
RemoveCompletedObjective(segments[4]);
|
||||||
yield return new WaitForSeconds(2f, false);
|
yield return new WaitForSeconds(2f, false);
|
||||||
|
|
||||||
@@ -557,19 +562,19 @@ namespace Barotrauma.Tutorials
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CheckJunctionBoxHighlights()
|
private void CheckJunctionBoxHighlights(Repairable comp1, Repairable comp2, Repairable comp3)
|
||||||
{
|
{
|
||||||
if (engineer_submarineJunctionBox_1.IsFullCondition && engineer_submarineJunctionBox_1.ExternalHighlight)
|
if (engineer_submarineJunctionBox_1.Condition > comp1.RepairThreshold && engineer_submarineJunctionBox_1.ExternalHighlight)
|
||||||
{
|
{
|
||||||
SetHighlight(engineer_submarineJunctionBox_1, false);
|
SetHighlight(engineer_submarineJunctionBox_1, false);
|
||||||
engineer.RemoveActiveObjectiveEntity(engineer_submarineJunctionBox_1);
|
engineer.RemoveActiveObjectiveEntity(engineer_submarineJunctionBox_1);
|
||||||
}
|
}
|
||||||
if (engineer_submarineJunctionBox_2.IsFullCondition && engineer_submarineJunctionBox_2.ExternalHighlight)
|
if (engineer_submarineJunctionBox_2.Condition > comp2.RepairThreshold && engineer_submarineJunctionBox_2.ExternalHighlight)
|
||||||
{
|
{
|
||||||
SetHighlight(engineer_submarineJunctionBox_2, false);
|
SetHighlight(engineer_submarineJunctionBox_2, false);
|
||||||
engineer.RemoveActiveObjectiveEntity(engineer_submarineJunctionBox_2);
|
engineer.RemoveActiveObjectiveEntity(engineer_submarineJunctionBox_2);
|
||||||
}
|
}
|
||||||
if (engineer_submarineJunctionBox_3.IsFullCondition && engineer_submarineJunctionBox_3.ExternalHighlight)
|
if (engineer_submarineJunctionBox_3.Condition > comp3.RepairThreshold && engineer_submarineJunctionBox_3.ExternalHighlight)
|
||||||
{
|
{
|
||||||
SetHighlight(engineer_submarineJunctionBox_3, false);
|
SetHighlight(engineer_submarineJunctionBox_3, false);
|
||||||
engineer.RemoveActiveObjectiveEntity(engineer_submarineJunctionBox_3);
|
engineer.RemoveActiveObjectiveEntity(engineer_submarineJunctionBox_3);
|
||||||
|
|||||||
+15
-9
@@ -385,7 +385,8 @@ namespace Barotrauma.Tutorials
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gotOxygenTank && mechanic.Inventory.FindItemByIdentifier("oxygentank") != null)
|
if (!gotOxygenTank && (mechanic.Inventory.FindItemByIdentifier("oxygentank") != null ||
|
||||||
|
mechanic_deconstructor.InputContainer.Inventory.FindItemByIdentifier("oxygentank") != null))
|
||||||
{
|
{
|
||||||
gotOxygenTank = true;
|
gotOxygenTank = true;
|
||||||
}
|
}
|
||||||
@@ -551,7 +552,7 @@ namespace Barotrauma.Tutorials
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
yield return null;
|
yield return null;
|
||||||
if (!mechanic_brokenPump.Item.IsFullCondition)
|
if (mechanic_brokenPump.Item.Condition < repairablePumpComponent.RepairThreshold)
|
||||||
{
|
{
|
||||||
if (!mechanic.HasEquippedItem("wrench"))
|
if (!mechanic.HasEquippedItem("wrench"))
|
||||||
{
|
{
|
||||||
@@ -575,7 +576,7 @@ namespace Barotrauma.Tutorials
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (!mechanic_brokenPump.Item.IsFullCondition || mechanic_brokenPump.FlowPercentage >= 0 || !mechanic_brokenPump.IsActive);
|
} while (mechanic_brokenPump.Item.Condition < repairablePumpComponent.RepairThreshold || mechanic_brokenPump.FlowPercentage >= 0 || !mechanic_brokenPump.IsActive);
|
||||||
RemoveCompletedObjective(segments[9]);
|
RemoveCompletedObjective(segments[9]);
|
||||||
SetHighlight(mechanic_brokenPump.Item, false);
|
SetHighlight(mechanic_brokenPump.Item, false);
|
||||||
do { yield return null; } while (mechanic_brokenhull_2.WaterPercentage > waterVolumeBeforeOpening);
|
do { yield return null; } while (mechanic_brokenhull_2.WaterPercentage > waterVolumeBeforeOpening);
|
||||||
@@ -592,9 +593,14 @@ namespace Barotrauma.Tutorials
|
|||||||
SetHighlight(mechanic_ballastPump_1.Item, true);
|
SetHighlight(mechanic_ballastPump_1.Item, true);
|
||||||
SetHighlight(mechanic_ballastPump_2.Item, true);
|
SetHighlight(mechanic_ballastPump_2.Item, true);
|
||||||
SetHighlight(mechanic_submarineEngine.Item, true);
|
SetHighlight(mechanic_submarineEngine.Item, true);
|
||||||
|
|
||||||
|
Repairable repairablePumpComponent1 = mechanic_ballastPump_1.Item.GetComponent<Repairable>();
|
||||||
|
Repairable repairablePumpComponent2 = mechanic_ballastPump_2.Item.GetComponent<Repairable>();
|
||||||
|
Repairable repairableEngineComponent = mechanic_submarineEngine.Item.GetComponent<Repairable>();
|
||||||
|
|
||||||
// Remove highlights when each individual machine is repaired
|
// Remove highlights when each individual machine is repaired
|
||||||
do { CheckHighlights(); yield return null; } while (!mechanic_ballastPump_1.Item.IsFullCondition || !mechanic_ballastPump_2.Item.IsFullCondition || !mechanic_submarineEngine.Item.IsFullCondition);
|
do { CheckHighlights(repairablePumpComponent1, repairablePumpComponent2, repairableEngineComponent); yield return null; } while (mechanic_ballastPump_1.Item.Condition < repairablePumpComponent1.RepairThreshold || mechanic_ballastPump_2.Item.Condition < repairablePumpComponent2.RepairThreshold || mechanic_submarineEngine.Item.Condition < repairableEngineComponent.RepairThreshold);
|
||||||
CheckHighlights();
|
CheckHighlights(repairablePumpComponent1, repairablePumpComponent2, repairableEngineComponent);
|
||||||
RemoveCompletedObjective(segments[10]);
|
RemoveCompletedObjective(segments[10]);
|
||||||
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.Complete"), ChatMessageType.Radio, null);
|
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.Complete"), ChatMessageType.Radio, null);
|
||||||
|
|
||||||
@@ -617,19 +623,19 @@ namespace Barotrauma.Tutorials
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CheckHighlights()
|
private void CheckHighlights(Repairable comp1, Repairable comp2, Repairable comp3)
|
||||||
{
|
{
|
||||||
if (mechanic_ballastPump_1.Item.IsFullCondition && mechanic_ballastPump_1.Item.ExternalHighlight)
|
if (mechanic_ballastPump_1.Item.Condition > comp1.RepairThreshold && mechanic_ballastPump_1.Item.ExternalHighlight)
|
||||||
{
|
{
|
||||||
SetHighlight(mechanic_ballastPump_1.Item, false);
|
SetHighlight(mechanic_ballastPump_1.Item, false);
|
||||||
mechanic.RemoveActiveObjectiveEntity(mechanic_ballastPump_1.Item);
|
mechanic.RemoveActiveObjectiveEntity(mechanic_ballastPump_1.Item);
|
||||||
}
|
}
|
||||||
if (mechanic_ballastPump_2.Item.IsFullCondition && mechanic_ballastPump_2.Item.ExternalHighlight)
|
if (mechanic_ballastPump_2.Item.Condition > comp2.RepairThreshold && mechanic_ballastPump_2.Item.ExternalHighlight)
|
||||||
{
|
{
|
||||||
SetHighlight(mechanic_ballastPump_2.Item, false);
|
SetHighlight(mechanic_ballastPump_2.Item, false);
|
||||||
mechanic.RemoveActiveObjectiveEntity(mechanic_ballastPump_2.Item);
|
mechanic.RemoveActiveObjectiveEntity(mechanic_ballastPump_2.Item);
|
||||||
}
|
}
|
||||||
if (mechanic_submarineEngine.Item.IsFullCondition && mechanic_submarineEngine.Item.ExternalHighlight)
|
if (mechanic_submarineEngine.Item.Condition > comp3.RepairThreshold && mechanic_submarineEngine.Item.ExternalHighlight)
|
||||||
{
|
{
|
||||||
SetHighlight(mechanic_submarineEngine.Item, false);
|
SetHighlight(mechanic_submarineEngine.Item, false);
|
||||||
mechanic.RemoveActiveObjectiveEntity(mechanic_submarineEngine.Item);
|
mechanic.RemoveActiveObjectiveEntity(mechanic_submarineEngine.Item);
|
||||||
|
|||||||
+8
-1
@@ -315,13 +315,14 @@ namespace Barotrauma.Tutorials
|
|||||||
yield return new WaitForSeconds(2f, false);
|
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, GameMain.Config.KeyBindText(InputType.Select), GameMain.Config.KeyBindText(InputType.Shoot), GameMain.Config.KeyBindText(InputType.Deselect)); // Kill hammerhead
|
||||||
officer_hammerhead = SpawnMonster("hammerhead", officer_hammerheadSpawnPos);
|
officer_hammerhead = SpawnMonster("hammerhead", officer_hammerheadSpawnPos);
|
||||||
|
((EnemyAIController)officer_hammerhead.AIController).StayInsideLevel = false;
|
||||||
officer_hammerhead.AIController.SelectTarget(officer.AiTarget);
|
officer_hammerhead.AIController.SelectTarget(officer.AiTarget);
|
||||||
SetHighlight(officer_coilgunPeriscope, true);
|
SetHighlight(officer_coilgunPeriscope, true);
|
||||||
float originalDistance = Vector2.Distance(officer_coilgunPeriscope.WorldPosition, officer_hammerheadSpawnPos);
|
float originalDistance = Vector2.Distance(officer_coilgunPeriscope.WorldPosition, officer_hammerheadSpawnPos);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
float distance = Vector2.Distance(officer_coilgunPeriscope.WorldPosition, officer_hammerhead.WorldPosition);
|
float distance = Vector2.Distance(officer_coilgunPeriscope.WorldPosition, officer_hammerhead.WorldPosition);
|
||||||
if (distance > originalDistance * 1.5f)
|
if (distance > originalDistance * 1.5f || officer_hammerhead.WorldPosition.Y > officer_coilgunPeriscope.WorldPosition.Y)
|
||||||
{
|
{
|
||||||
// Don't let the Hammerhead go too far.
|
// Don't let the Hammerhead go too far.
|
||||||
officer_hammerhead.TeleportTo(officer_hammerheadSpawnPos + new Vector2(0, -1000));
|
officer_hammerhead.TeleportTo(officer_hammerheadSpawnPos + new Vector2(0, -1000));
|
||||||
@@ -329,7 +330,13 @@ namespace Barotrauma.Tutorials
|
|||||||
if (distance > originalDistance)
|
if (distance > originalDistance)
|
||||||
{
|
{
|
||||||
// Ensure that the Hammerhead targets the player
|
// Ensure that the Hammerhead targets the player
|
||||||
|
officer.AiTarget.SoundRange = float.MaxValue;
|
||||||
|
officer.AiTarget.SightRange = float.MaxValue;
|
||||||
officer_hammerhead.AIController.SelectTarget(officer.AiTarget);
|
officer_hammerhead.AIController.SelectTarget(officer.AiTarget);
|
||||||
|
if ((officer_hammerhead.AIController as EnemyAIController)?.SelectedTargetingParams != null)
|
||||||
|
{
|
||||||
|
((EnemyAIController)officer_hammerhead.AIController).SelectedTargetingParams.ReactDistance = 5000.0f;
|
||||||
|
}
|
||||||
/*var ai = officer_hammerhead.AIController as EnemyAIController;
|
/*var ai = officer_hammerhead.AIController as EnemyAIController;
|
||||||
ai.sight = 2.0f;*/
|
ai.sight = 2.0f;*/
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-18
@@ -58,30 +58,31 @@ namespace Barotrauma.Tutorials
|
|||||||
{
|
{
|
||||||
SubmarineInfo subInfo = new SubmarineInfo(submarinePath);
|
SubmarineInfo subInfo = new SubmarineInfo(submarinePath);
|
||||||
|
|
||||||
LevelGenerationParams generationParams = LevelGenerationParams.LevelParams.Find(p => p.Name == levelParams);
|
LevelGenerationParams generationParams = LevelGenerationParams.LevelParams.Find(p => p.Identifier.Equals(levelParams, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
yield return CoroutineStatus.Running;
|
yield return CoroutineStatus.Running;
|
||||||
|
|
||||||
GameMain.GameSession = new GameSession(subInfo, "",
|
GameMain.GameSession = new GameSession(subInfo, GameModePreset.Tutorial, missionPrefab: null);
|
||||||
GameModePreset.List.Find(g => g.Identifier == "tutorial"));
|
|
||||||
(GameMain.GameSession.GameMode as TutorialMode).Tutorial = this;
|
(GameMain.GameSession.GameMode as TutorialMode).Tutorial = this;
|
||||||
|
|
||||||
if (generationParams != null)
|
if (generationParams != null)
|
||||||
{
|
{
|
||||||
Biome biome = LevelGenerationParams.GetBiomes().Find(b => generationParams.AllowedBiomes.Contains(b));
|
Biome biome =
|
||||||
|
LevelGenerationParams.GetBiomes().FirstOrDefault(b => generationParams.AllowedBiomes.Contains(b)) ??
|
||||||
|
LevelGenerationParams.GetBiomes().First();
|
||||||
|
|
||||||
if (startOutpostPath != string.Empty)
|
if (!string.IsNullOrEmpty(startOutpostPath))
|
||||||
{
|
{
|
||||||
startOutpost = new SubmarineInfo(startOutpostPath);
|
startOutpost = new SubmarineInfo(startOutpostPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (endOutpostPath != string.Empty)
|
if (!string.IsNullOrEmpty(endOutpostPath))
|
||||||
{
|
{
|
||||||
endOutpost = new SubmarineInfo(endOutpostPath);
|
endOutpost = new SubmarineInfo(endOutpostPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
Level tutorialLevel = new Level(levelSeed, 0, 0, generationParams, biome, startOutpost, endOutpost);
|
LevelData tutorialLevel = new LevelData(levelSeed, 0, 0, generationParams, biome);
|
||||||
GameMain.GameSession.StartRound(tutorialLevel);
|
GameMain.GameSession.StartRound(tutorialLevel, startOutpost: startOutpost, endOutpost: endOutpost);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -100,6 +101,13 @@ namespace Barotrauma.Tutorials
|
|||||||
base.Start();
|
base.Start();
|
||||||
|
|
||||||
Submarine.MainSub.GodMode = true;
|
Submarine.MainSub.GodMode = true;
|
||||||
|
foreach (Structure wall in Structure.WallList)
|
||||||
|
{
|
||||||
|
if (wall.Submarine != null && wall.Submarine.Info.IsOutpost)
|
||||||
|
{
|
||||||
|
wall.Indestructible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CharacterInfo charInfo = configElement.Element("Character") == null ?
|
CharacterInfo charInfo = configElement.Element("Character") == null ?
|
||||||
new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("engineer")) :
|
new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("engineer")) :
|
||||||
@@ -114,6 +122,7 @@ namespace Barotrauma.Tutorials
|
|||||||
}
|
}
|
||||||
|
|
||||||
character = Character.Create(charInfo, wayPoint.WorldPosition, "", false, false);
|
character = Character.Create(charInfo, wayPoint.WorldPosition, "", false, false);
|
||||||
|
character.TeamID = Character.TeamType.Team1;
|
||||||
Character.Controlled = character;
|
Character.Controlled = character;
|
||||||
character.GiveJobItems(null);
|
character.GiveJobItems(null);
|
||||||
|
|
||||||
@@ -126,17 +135,12 @@ namespace Barotrauma.Tutorials
|
|||||||
idCard.AddTag("com");
|
idCard.AddTag("com");
|
||||||
idCard.AddTag("eng");
|
idCard.AddTag("eng");
|
||||||
|
|
||||||
List<Entity> entities = Entity.GetEntityList();
|
foreach (Item item in Item.ItemList)
|
||||||
|
|
||||||
for (int i = 0; i < entities.Count; i++)
|
|
||||||
{
|
{
|
||||||
if (entities[i] is Item)
|
Door door = item.GetComponent<Door>();
|
||||||
|
if (door != null)
|
||||||
{
|
{
|
||||||
Door door = (entities[i] as Item).GetComponent<Door>();
|
door.CanBeWelded = false;
|
||||||
if (door != null)
|
|
||||||
{
|
|
||||||
door.CanBeWelded = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,7 +288,7 @@ namespace Barotrauma.Tutorials
|
|||||||
|
|
||||||
yield return new WaitForSeconds(waitBeforeFade);
|
yield return new WaitForSeconds(waitBeforeFade);
|
||||||
|
|
||||||
var endCinematic = new RoundEndCinematic(Submarine.MainSub, GameMain.GameScreen.Cam, fadeOutTime);
|
var endCinematic = new CameraTransition(Submarine.MainSub, GameMain.GameScreen.Cam, null, Alignment.Center, duration: fadeOutTime);
|
||||||
currentTutorialCompleted = Completed = true;
|
currentTutorialCompleted = Completed = true;
|
||||||
while (endCinematic.Running) yield return null;
|
while (endCinematic.Running) yield return null;
|
||||||
Stop();
|
Stop();
|
||||||
|
|||||||
+3
-1
@@ -26,6 +26,7 @@ namespace Barotrauma.Tutorials
|
|||||||
protected enum TutorialContentTypes { None = 0, Video = 1, ManualVideo = 2, TextOnly = 3 };
|
protected enum TutorialContentTypes { None = 0, Video = 1, ManualVideo = 2, TextOnly = 3 };
|
||||||
protected string playableContentPath;
|
protected string playableContentPath;
|
||||||
protected Point screenResolution;
|
protected Point screenResolution;
|
||||||
|
protected WindowMode windowMode;
|
||||||
protected float prevUIScale;
|
protected float prevUIScale;
|
||||||
|
|
||||||
private GUIFrame holderFrame, objectiveFrame;
|
private GUIFrame holderFrame, objectiveFrame;
|
||||||
@@ -207,7 +208,7 @@ namespace Barotrauma.Tutorials
|
|||||||
|
|
||||||
public virtual void AddToGUIUpdateList()
|
public virtual void AddToGUIUpdateList()
|
||||||
{
|
{
|
||||||
if (GameMain.GraphicsWidth != screenResolution.X || GameMain.GraphicsHeight != screenResolution.Y || prevUIScale != GUI.Scale)
|
if (GameMain.GraphicsWidth != screenResolution.X || GameMain.GraphicsHeight != screenResolution.Y || prevUIScale != GUI.Scale || GameMain.Config.WindowMode != windowMode)
|
||||||
{
|
{
|
||||||
CreateObjectiveFrame();
|
CreateObjectiveFrame();
|
||||||
}
|
}
|
||||||
@@ -340,6 +341,7 @@ namespace Barotrauma.Tutorials
|
|||||||
}
|
}
|
||||||
|
|
||||||
screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||||
|
windowMode = GameMain.Config.WindowMode;
|
||||||
prevUIScale = GUI.Scale;
|
prevUIScale = GUI.Scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-2
@@ -11,8 +11,8 @@ namespace Barotrauma
|
|||||||
tutorial.Initialize();
|
tutorial.Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public TutorialMode(GameModePreset preset, object param)
|
public TutorialMode(GameModePreset preset)
|
||||||
: base(preset, param)
|
: base(preset)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,6 +21,11 @@ namespace Barotrauma
|
|||||||
base.Start();
|
base.Start();
|
||||||
GameMain.GameSession.CrewManager = new CrewManager(true);
|
GameMain.GameSession.CrewManager = new CrewManager(true);
|
||||||
Tutorial.Start();
|
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
|
||||||
|
item.SpawnedInOutpost = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void AddToGUIUpdateList()
|
public override void AddToGUIUpdateList()
|
||||||
|
|||||||
@@ -1,14 +1,19 @@
|
|||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using Microsoft.Xna.Framework.Input;
|
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
partial class GameSession
|
partial class GameSession
|
||||||
{
|
{
|
||||||
public RoundSummary RoundSummary { get; private set; }
|
public RoundSummary RoundSummary
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
public static bool IsTabMenuOpen => GameMain.GameSession?.tabMenu != null;
|
public static bool IsTabMenuOpen => GameMain.GameSession?.tabMenu != null;
|
||||||
public static TabMenu TabMenuInstance => GameMain.GameSession?.tabMenu;
|
public static TabMenu TabMenuInstance => GameMain.GameSession?.tabMenu;
|
||||||
|
|
||||||
|
|
||||||
private TabMenu tabMenu;
|
private TabMenu tabMenu;
|
||||||
|
|
||||||
public bool ToggleTabMenu()
|
public bool ToggleTabMenu()
|
||||||
@@ -46,30 +51,20 @@ namespace Barotrauma
|
|||||||
|
|
||||||
partial void UpdateProjSpecific(float deltaTime)
|
partial void UpdateProjSpecific(float deltaTime)
|
||||||
{
|
{
|
||||||
if (GUI.DisableHUD) return;
|
if (GUI.DisableHUD) { return; }
|
||||||
|
|
||||||
if (GameMode.IsRunning)
|
if (tabMenu == null)
|
||||||
{
|
{
|
||||||
if (tabMenu == null)
|
if (PlayerInput.KeyHit(InputType.InfoTab) && GUI.KeyboardDispatcher.Subscriber is GUITextBox == false)
|
||||||
{
|
{
|
||||||
if (PlayerInput.KeyHit(InputType.InfoTab) && GUI.KeyboardDispatcher.Subscriber is GUITextBox == false)
|
ToggleTabMenu();
|
||||||
{
|
|
||||||
ToggleTabMenu();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tabMenu.Update();
|
|
||||||
|
|
||||||
if (PlayerInput.KeyHit(InputType.InfoTab) && GUI.KeyboardDispatcher.Subscriber is GUITextBox == false)
|
|
||||||
{
|
|
||||||
ToggleTabMenu();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (tabMenu != null)
|
tabMenu.Update();
|
||||||
|
|
||||||
|
if (PlayerInput.KeyHit(InputType.InfoTab) && GUI.KeyboardDispatcher.Subscriber is GUITextBox == false)
|
||||||
{
|
{
|
||||||
ToggleTabMenu();
|
ToggleTabMenu();
|
||||||
}
|
}
|
||||||
@@ -97,7 +92,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void Draw(SpriteBatch spriteBatch)
|
public void Draw(SpriteBatch spriteBatch)
|
||||||
{
|
{
|
||||||
if (GUI.DisableHUD) return;
|
|
||||||
GameMode?.Draw(spriteBatch);
|
GameMode?.Draw(spriteBatch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,185 +1,654 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
class RoundSummary
|
class RoundSummary
|
||||||
{
|
{
|
||||||
private Location startLocation, endLocation;
|
private const float jobColumnWidthPercentage = 0.11f;
|
||||||
|
private const float characterColumnWidthPercentage = 0.44f;
|
||||||
|
private const float statusColumnWidthPercentage = 0.45f;
|
||||||
|
|
||||||
private GameSession gameSession;
|
private int jobColumnWidth, characterColumnWidth, statusColumnWidth;
|
||||||
|
|
||||||
private Mission selectedMission;
|
private readonly SubmarineInfo sub;
|
||||||
|
private readonly Mission selectedMission;
|
||||||
|
private readonly Location startLocation, endLocation;
|
||||||
|
|
||||||
public RoundSummary(GameSession gameSession)
|
private readonly GameMode gameMode;
|
||||||
|
|
||||||
|
private readonly float initialLocationReputation;
|
||||||
|
private readonly Dictionary<Faction, float> initialFactionReputations = new Dictionary<Faction, float>();
|
||||||
|
|
||||||
|
public GUILayoutGroup ButtonArea { get; private set; }
|
||||||
|
|
||||||
|
public GUIButton ContinueButton { get; private set; }
|
||||||
|
|
||||||
|
public GUIComponent Frame { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public RoundSummary(SubmarineInfo sub, GameMode gameMode, Mission selectedMission, Location startLocation, Location endLocation)
|
||||||
{
|
{
|
||||||
this.gameSession = gameSession;
|
this.sub = sub;
|
||||||
|
this.gameMode = gameMode;
|
||||||
startLocation = gameSession.StartLocation;
|
this.selectedMission = selectedMission;
|
||||||
endLocation = gameSession.EndLocation;
|
this.startLocation = startLocation;
|
||||||
|
this.endLocation = endLocation;
|
||||||
selectedMission = gameSession.Mission;
|
initialLocationReputation = startLocation?.Reputation?.Value ?? 0.0f;
|
||||||
|
if (gameMode is CampaignMode campaignMode)
|
||||||
|
{
|
||||||
|
foreach (Faction faction in campaignMode.Factions)
|
||||||
|
{
|
||||||
|
initialFactionReputations.Add(faction, faction.Reputation.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public GUIFrame CreateSummaryFrame(string endMessage)
|
public GUIFrame CreateSummaryFrame(GameSession gameSession, string endMessage, List<TraitorMissionResult> traitorResults, CampaignMode.TransitionType transitionType = CampaignMode.TransitionType.None)
|
||||||
{
|
{
|
||||||
bool singleplayer = GameMain.NetworkMember == null;
|
bool singleplayer = GameMain.NetworkMember == null;
|
||||||
bool gameOver = gameSession.CrewManager.GetCharacters().All(c => c.IsDead || c.IsIncapacitated);
|
bool gameOver =
|
||||||
bool progress = Submarine.MainSub.AtEndPosition;
|
gameSession.GameMode.IsSinglePlayer ?
|
||||||
|
gameSession.CrewManager.GetCharacters().All(c => c.IsDead || c.IsIncapacitated) :
|
||||||
|
gameSession.CrewManager.GetCharacters().All(c => c.IsDead || c.IsIncapacitated || c.IsBot);
|
||||||
|
|
||||||
if (!singleplayer)
|
if (!singleplayer)
|
||||||
{
|
{
|
||||||
SoundPlayer.OverrideMusicType = gameOver ? "crewdead" : "endround";
|
SoundPlayer.OverrideMusicType = gameOver ? "crewdead" : "endround";
|
||||||
SoundPlayer.OverrideMusicDuration = 18.0f;
|
SoundPlayer.OverrideMusicDuration = 18.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
GUIFrame background = new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, GUI.Canvas, Anchor.Center), style: "GUIBackgroundBlocker");
|
GUIFrame background = new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, GUI.Canvas, Anchor.Center), style: "GUIBackgroundBlocker")
|
||||||
|
|
||||||
GUIFrame frame = new GUIFrame(new RectTransform(Vector2.One, background.RectTransform, Anchor.Center), style: null)
|
|
||||||
{
|
{
|
||||||
UserData = "roundsummary"
|
UserData = this
|
||||||
};
|
};
|
||||||
|
|
||||||
int width = 760, height = 500;
|
List<GUIComponent> rightPanels = new List<GUIComponent>();
|
||||||
GUIFrame innerFrame = new GUIFrame(new RectTransform(new Vector2(0.4f, 0.5f), frame.RectTransform, Anchor.Center, minSize: new Point(width, height)));
|
|
||||||
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), innerFrame.RectTransform, Anchor.Center))
|
int minWidth = 400, minHeight = 350;
|
||||||
|
int padding = GUI.IntScale(25.0f);
|
||||||
|
|
||||||
|
//crew panel -------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
GUIFrame crewFrame = new GUIFrame(new RectTransform(new Vector2(0.35f, 0.55f), background.RectTransform, Anchor.TopCenter, minSize: new Point(minWidth, minHeight)));
|
||||||
|
GUIFrame crewFrameInner = new GUIFrame(new RectTransform(new Point(crewFrame.Rect.Width - padding * 2, crewFrame.Rect.Height - padding * 2), crewFrame.RectTransform, Anchor.Center), style: "InnerFrame");
|
||||||
|
|
||||||
|
var crewContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), crewFrameInner.RectTransform, Anchor.Center))
|
||||||
{
|
{
|
||||||
Stretch = true,
|
Stretch = true
|
||||||
RelativeSpacing = 0.03f
|
|
||||||
};
|
};
|
||||||
|
|
||||||
GUIListBox infoTextBox = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.7f), paddedFrame.RectTransform))
|
var crewHeader = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), crewContent.RectTransform),
|
||||||
|
TextManager.Get("crew"), textAlignment: Alignment.TopLeft, font: GUI.SubHeadingFont);
|
||||||
|
crewHeader.RectTransform.MinSize = new Point(0, GUI.IntScale(crewHeader.Rect.Height * 2.0f));
|
||||||
|
|
||||||
|
CreateCrewList(crewContent, gameSession.CrewManager.GetCharacterInfos().Where(c => c.TeamID != Character.TeamType.Team2));
|
||||||
|
|
||||||
|
//another crew frame for the 2nd team in combat missions
|
||||||
|
if (gameSession.Mission is CombatMission)
|
||||||
{
|
{
|
||||||
Spacing = (int)(5 * GUI.Scale)
|
crewHeader.Text = CombatMission.GetTeamName(Character.TeamType.Team1);
|
||||||
};
|
GUIFrame crewFrame2 = new GUIFrame(new RectTransform(new Vector2(0.35f, 0.55f), background.RectTransform, Anchor.TopCenter, minSize: new Point(minWidth, minHeight)));
|
||||||
|
rightPanels.Add(crewFrame2);
|
||||||
//spacing
|
GUIFrame crewFrameInner2 = new GUIFrame(new RectTransform(new Point(crewFrame2.Rect.Width - padding * 2, crewFrame2.Rect.Height - padding * 2), crewFrame2.RectTransform, Anchor.Center), style: "InnerFrame");
|
||||||
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), infoTextBox.Content.RectTransform), style: null);
|
var crewContent2 = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), crewFrameInner2.RectTransform, Anchor.Center))
|
||||||
|
{
|
||||||
string summaryText = TextManager.GetWithVariables(gameOver ? "RoundSummaryGameOver" :
|
Stretch = true
|
||||||
(progress ? "RoundSummaryProgress" : "RoundSummaryReturn"), new string[2] { "[sub]", "[location]" },
|
};
|
||||||
new string[2] { Submarine.MainSub.Info.Name, progress ? GameMain.GameSession.EndLocation.Name : GameMain.GameSession.StartLocation.Name });
|
var crewHeader2 = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), crewContent2.RectTransform),
|
||||||
|
CombatMission.GetTeamName(Character.TeamType.Team2), textAlignment: Alignment.TopLeft, font: GUI.SubHeadingFont);
|
||||||
var infoText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoTextBox.Content.RectTransform),
|
crewHeader2.RectTransform.MinSize = new Point(0, GUI.IntScale(crewHeader2.Rect.Height * 2.0f));
|
||||||
summaryText, wrap: true);
|
CreateCrewList(crewContent2, gameSession.CrewManager.GetCharacterInfos().Where(c => c.TeamID == Character.TeamType.Team2));
|
||||||
|
|
||||||
GUIComponent endText = null;
|
|
||||||
if (!string.IsNullOrWhiteSpace(endMessage))
|
|
||||||
{
|
|
||||||
endText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoTextBox.Content.RectTransform),
|
|
||||||
TextManager.GetServerMessage(endMessage), wrap: true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//don't show the mission info if the mission was not completed and there's no localized "mission failed" text available
|
//header -------------------------------------------------------------------------------
|
||||||
if (GameMain.GameSession.Mission != null)
|
|
||||||
|
string headerText = GetHeaderText(gameOver, transitionType);
|
||||||
|
GUITextBlock headerTextBlock = null;
|
||||||
|
if (!string.IsNullOrEmpty(headerText))
|
||||||
{
|
{
|
||||||
string message = GameMain.GameSession.Mission.Completed ? GameMain.GameSession.Mission.SuccessMessage : GameMain.GameSession.Mission.FailureMessage;
|
headerTextBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), crewFrame.RectTransform, Anchor.TopLeft, Pivot.BottomLeft),
|
||||||
if (!string.IsNullOrEmpty(message))
|
headerText, textAlignment: Alignment.BottomLeft, font: GUI.LargeFont, wrap: true);
|
||||||
{
|
|
||||||
//spacing
|
|
||||||
var spacingTransform = new RectTransform(new Vector2(1.0f, 0.1f), infoTextBox.Content.RectTransform);
|
|
||||||
|
|
||||||
new GUIFrame(spacingTransform, style: null);
|
|
||||||
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoTextBox.Content.RectTransform),
|
|
||||||
TextManager.AddPunctuation(':', TextManager.Get("Mission"), GameMain.GameSession.Mission.Name),
|
|
||||||
font: GUI.LargeFont);
|
|
||||||
|
|
||||||
var missionInfo = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoTextBox.Content.RectTransform),
|
|
||||||
message, wrap: true);
|
|
||||||
|
|
||||||
if (GameMain.GameSession.Mission.Completed && singleplayer)
|
|
||||||
{
|
|
||||||
var missionReward = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoTextBox.Content.RectTransform),
|
|
||||||
TextManager.GetWithVariable("MissionReward", "[reward]", GameMain.GameSession.Mission.Reward.ToString()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform),
|
//traitor panel -------------------------------------------------------------------------------
|
||||||
TextManager.Get("RoundSummaryCrewStatus"), font: GUI.LargeFont);
|
|
||||||
|
|
||||||
GUIListBox characterListBox = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.4f), paddedFrame.RectTransform, minSize: new Point(0, 75)), isHorizontal: true);
|
if (traitorResults != null && traitorResults.Any())
|
||||||
|
|
||||||
foreach (CharacterInfo characterInfo in gameSession.CrewManager.GetCharacterInfos())
|
|
||||||
{
|
{
|
||||||
if (GameMain.GameSession.Mission is CombatMission &&
|
GUIFrame traitorframe = new GUIFrame(new RectTransform(crewFrame.RectTransform.RelativeSize, background.RectTransform, Anchor.TopCenter, minSize: crewFrame.RectTransform.MinSize));
|
||||||
characterInfo.TeamID != GameMain.GameSession.WinningTeam)
|
rightPanels.Add(traitorframe);
|
||||||
{
|
GUIFrame traitorframeInner = new GUIFrame(new RectTransform(new Point(traitorframe.Rect.Width - padding * 2, traitorframe.Rect.Height - padding * 2), traitorframe.RectTransform, Anchor.Center), style: "InnerFrame");
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var characterFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.2f, 1.0f), characterListBox.Content.RectTransform, minSize: new Point(170, 0)))
|
var traitorContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), traitorframeInner.RectTransform, Anchor.Center))
|
||||||
{
|
{
|
||||||
CanBeFocused = false,
|
|
||||||
Stretch = true
|
Stretch = true
|
||||||
};
|
};
|
||||||
|
|
||||||
characterInfo.CreateCharacterFrame(characterFrame,
|
var traitorHeader = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), traitorContent.RectTransform),
|
||||||
characterInfo.Job != null ? (characterInfo.Name + '\n' + "(" + characterInfo.Job.Name + ")") : characterInfo.Name, null);
|
TextManager.Get("traitors"), font: GUI.SubHeadingFont);
|
||||||
|
traitorHeader.RectTransform.MinSize = new Point(0, GUI.IntScale(traitorHeader.Rect.Height * 2.0f));
|
||||||
|
|
||||||
string statusText = TextManager.Get("StatusOK");
|
GUIListBox listBox = CreateCrewList(traitorContent, traitorResults.SelectMany(tr => tr.Characters.Select(c => c.Info)));
|
||||||
Color statusColor = Color.DarkGreen;
|
|
||||||
|
|
||||||
Character character = characterInfo.Character;
|
foreach (var traitorResult in traitorResults)
|
||||||
if (character == null || character.IsDead)
|
|
||||||
{
|
{
|
||||||
if (characterInfo.CauseOfDeath == null)
|
var traitorMission = TraitorMissionPrefab.List.Find(t => t.Identifier == traitorResult.MissionIdentifier);
|
||||||
|
if (traitorMission == null) { continue; }
|
||||||
|
|
||||||
|
//spacing
|
||||||
|
new GUIFrame(new RectTransform(new Point(listBox.Content.Rect.Width, GUI.IntScale(25)), listBox.Content.RectTransform), style: null);
|
||||||
|
|
||||||
|
var traitorResultHorizontal = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.3f), listBox.Content.RectTransform), childAnchor: Anchor.CenterLeft, isHorizontal: true)
|
||||||
{
|
{
|
||||||
statusText = TextManager.Get("CauseOfDeathDescription.Unknown");
|
RelativeSpacing = 0.05f,
|
||||||
|
Stretch = true
|
||||||
|
};
|
||||||
|
|
||||||
|
new GUIImage(new RectTransform(new Point(traitorResultHorizontal.Rect.Height), traitorResultHorizontal.RectTransform), traitorMission.Icon, scaleToFit: true)
|
||||||
|
{
|
||||||
|
Color = traitorMission.IconColor
|
||||||
|
};
|
||||||
|
|
||||||
|
string traitorMessage = TextManager.GetServerMessage(traitorResult.EndMessage);
|
||||||
|
if (!string.IsNullOrEmpty(traitorMessage))
|
||||||
|
{
|
||||||
|
var textContent = new GUILayoutGroup(new RectTransform(Vector2.One, traitorResultHorizontal.RectTransform))
|
||||||
|
{
|
||||||
|
RelativeSpacing = 0.025f
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
var traitorMissionInfo = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), textContent.RectTransform),
|
||||||
|
traitorMessage, font: GUI.SmallFont, wrap: true);
|
||||||
|
|
||||||
|
traitorResultHorizontal.Recalculate();
|
||||||
|
|
||||||
|
traitorStatusText.CalculateHeightFromText();
|
||||||
|
traitorMissionInfo.CalculateHeightFromText();
|
||||||
|
traitorStatusText.RectTransform.MinSize = new Point(0, traitorStatusText.Rect.Height);
|
||||||
|
traitorMissionInfo.RectTransform.MinSize = new Point(0, traitorMissionInfo.Rect.Height);
|
||||||
|
textContent.RectTransform.MaxSize = new Point(int.MaxValue, (int)((traitorStatusText.Rect.Height + traitorMissionInfo.Rect.Height) * 1.2f));
|
||||||
|
traitorResultHorizontal.RectTransform.MinSize = new Point(0, traitorStatusText.RectTransform.MinSize.Y + traitorMissionInfo.RectTransform.MinSize.Y);
|
||||||
}
|
}
|
||||||
else if (characterInfo.CauseOfDeath.Type == CauseOfDeathType.Affliction && characterInfo.CauseOfDeath.Affliction == null)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//reputation panel -------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
if (gameMode is CampaignMode campaignMode)
|
||||||
|
{
|
||||||
|
GUIFrame reputationframe = new GUIFrame(new RectTransform(crewFrame.RectTransform.RelativeSize, background.RectTransform, Anchor.TopCenter, minSize: crewFrame.RectTransform.MinSize));
|
||||||
|
rightPanels.Add(reputationframe);
|
||||||
|
GUIFrame reputationframeInner = new GUIFrame(new RectTransform(new Point(reputationframe.Rect.Width - padding * 2, reputationframe.Rect.Height - padding * 2), reputationframe.RectTransform, Anchor.Center), style: "InnerFrame");
|
||||||
|
|
||||||
|
var reputationContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), reputationframeInner.RectTransform, Anchor.Center))
|
||||||
|
{
|
||||||
|
Stretch = true
|
||||||
|
};
|
||||||
|
|
||||||
|
var reputationHeader = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), reputationContent.RectTransform),
|
||||||
|
TextManager.Get("reputation"), textAlignment: Alignment.TopLeft, font: GUI.SubHeadingFont);
|
||||||
|
reputationHeader.RectTransform.MinSize = new Point(0, GUI.IntScale(reputationHeader.Rect.Height * 2.0f));
|
||||||
|
|
||||||
|
GUIListBox reputationList = new GUIListBox(new RectTransform(Vector2.One, reputationContent.RectTransform))
|
||||||
|
{
|
||||||
|
Padding = new Vector4(2, 5, 0, 0)
|
||||||
|
};
|
||||||
|
reputationList.ContentBackground.Color = Color.Transparent;
|
||||||
|
|
||||||
|
if (startLocation.Type.HasOutpost && startLocation.Reputation != null)
|
||||||
|
{
|
||||||
|
var iconStyle = GUI.Style.GetComponentStyle("LocationReputationIcon");
|
||||||
|
CreateReputationElement(
|
||||||
|
reputationList.Content,
|
||||||
|
startLocation.Name,
|
||||||
|
startLocation.Reputation.Value, startLocation.Reputation.NormalizedValue, initialLocationReputation,
|
||||||
|
startLocation.Type.Name, "",
|
||||||
|
iconStyle?.GetDefaultSprite(), startLocation.Type.GetPortrait(0), iconStyle?.Color ?? Color.White);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Faction faction in campaignMode.Factions)
|
||||||
|
{
|
||||||
|
float initialReputation = faction.Reputation.Value;
|
||||||
|
if (initialFactionReputations.ContainsKey(faction))
|
||||||
{
|
{
|
||||||
string errorMsg = "Character \"" + character.Name + "\" had an invalid cause of death (the type of the cause of death was Affliction, but affliction was not specified).";
|
initialReputation = initialFactionReputations[faction];
|
||||||
DebugConsole.ThrowError(errorMsg);
|
|
||||||
GameAnalyticsManager.AddErrorEventOnce("RoundSummary:InvalidCauseOfDeath", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
|
||||||
statusText = TextManager.Get("CauseOfDeathDescription.Unknown");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
statusText = characterInfo.CauseOfDeath.Type == CauseOfDeathType.Affliction ?
|
DebugConsole.AddWarning($"Could not determine reputation change for faction \"{faction.Prefab.Name}\" (faction was not present at the start of the round).");
|
||||||
characterInfo.CauseOfDeath.Affliction.CauseOfDeathDescription :
|
|
||||||
TextManager.Get("CauseOfDeathDescription." + characterInfo.CauseOfDeath.Type.ToString());
|
|
||||||
}
|
}
|
||||||
|
CreateReputationElement(
|
||||||
|
reputationList.Content,
|
||||||
|
faction.Prefab.Name,
|
||||||
|
faction.Reputation.Value, faction.Reputation.NormalizedValue, initialReputation,
|
||||||
|
faction.Prefab.ShortDescription, faction.Prefab.Description,
|
||||||
|
faction.Prefab.Icon, faction.Prefab.BackgroundPortrait, faction.Prefab.IconColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
float otherElementHeight = 0.0f;
|
||||||
|
float maxDescriptionHeight = 0.0f;
|
||||||
|
foreach (GUIComponent child in reputationList.Content.Children)
|
||||||
|
{
|
||||||
|
var descriptionElement = child.FindChild("description", recursive: true) as GUITextBlock;
|
||||||
|
maxDescriptionHeight = Math.Max(maxDescriptionHeight, descriptionElement.TextSize.Y * 1.1f);
|
||||||
|
otherElementHeight = Math.Max(otherElementHeight, descriptionElement.Parent.Rect.Height - descriptionElement.TextSize.Y);
|
||||||
|
}
|
||||||
|
foreach (GUIComponent child in reputationList.Content.Children)
|
||||||
|
{
|
||||||
|
var descriptionElement = child.FindChild("description", recursive: true) as GUITextBlock;
|
||||||
|
descriptionElement.RectTransform.MaxSize = new Point(int.MaxValue, (int)(maxDescriptionHeight));
|
||||||
|
child.RectTransform.MaxSize = new Point(int.MaxValue, (int)((maxDescriptionHeight + otherElementHeight) * 1.2f));
|
||||||
|
(descriptionElement?.Parent as GUILayoutGroup).Recalculate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//mission panel -------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
GUIFrame missionframe = new GUIFrame(new RectTransform(new Vector2(0.39f, 0.22f), background.RectTransform, Anchor.TopCenter, minSize: new Point(minWidth, minHeight / 4)));
|
||||||
|
GUIFrame missionframeInner = new GUIFrame(new RectTransform(new Point(missionframe.Rect.Width - padding * 2, missionframe.Rect.Height - padding * 2), missionframe.RectTransform, Anchor.Center), style: "InnerFrame");
|
||||||
|
|
||||||
|
var missionContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), missionframeInner.RectTransform, Anchor.Center))
|
||||||
|
{
|
||||||
|
RelativeSpacing = 0.05f,
|
||||||
|
Stretch = true
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(endMessage))
|
||||||
|
{
|
||||||
|
var endText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionContent.RectTransform),
|
||||||
|
TextManager.GetServerMessage(endMessage), wrap: true);
|
||||||
|
endText.RectTransform.MinSize = new Point(0, endText.Rect.Height);
|
||||||
|
var line = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.1f), missionContent.RectTransform), style: "HorizontalLine");
|
||||||
|
line.RectTransform.NonScaledSize = new Point(line.Rect.Width, GUI.IntScale(5.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
var missionContentHorizontal = new GUILayoutGroup(new RectTransform(Vector2.One, missionContent.RectTransform), childAnchor: Anchor.TopLeft, isHorizontal: true)
|
||||||
|
{
|
||||||
|
RelativeSpacing = 0.025f,
|
||||||
|
Stretch = true
|
||||||
|
};
|
||||||
|
|
||||||
|
Mission displayedMission = selectedMission ?? startLocation.SelectedMission;
|
||||||
|
string missionMessage = "";
|
||||||
|
GUIImage missionIcon;
|
||||||
|
if (displayedMission != null)
|
||||||
|
{
|
||||||
|
missionMessage =
|
||||||
|
displayedMission == selectedMission ?
|
||||||
|
displayedMission.Completed ? displayedMission.SuccessMessage : displayedMission.FailureMessage :
|
||||||
|
displayedMission.Description;
|
||||||
|
missionIcon = new GUIImage(new RectTransform(new Point(missionContentHorizontal.Rect.Height), missionContentHorizontal.RectTransform), displayedMission.Prefab.Icon, scaleToFit: true)
|
||||||
|
{
|
||||||
|
Color = displayedMission.Prefab.IconColor
|
||||||
|
};
|
||||||
|
if (displayedMission == selectedMission)
|
||||||
|
{
|
||||||
|
new GUIImage(new RectTransform(Vector2.One, missionIcon.RectTransform), displayedMission.Completed ? "MissionCompletedIcon" : "MissionFailedIcon", scaleToFit: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
missionIcon = new GUIImage(new RectTransform(new Point(missionContentHorizontal.Rect.Height), missionContentHorizontal.RectTransform), style: "NoMissionIcon", scaleToFit: true);
|
||||||
|
}
|
||||||
|
var missionTextContent = new GUILayoutGroup(new RectTransform(Vector2.One, missionContentHorizontal.RectTransform))
|
||||||
|
{
|
||||||
|
RelativeSpacing = 0.05f
|
||||||
|
};
|
||||||
|
missionContentHorizontal.Recalculate();
|
||||||
|
missionContent.Recalculate();
|
||||||
|
missionIcon.RectTransform.MinSize = new Point(0, missionContentHorizontal.Rect.Height);
|
||||||
|
missionTextContent.RectTransform.MaxSize = new Point(int.MaxValue, missionIcon.Rect.Width);
|
||||||
|
|
||||||
|
GUITextBlock missionDescription = null;
|
||||||
|
if (displayedMission == null)
|
||||||
|
{
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform),
|
||||||
|
TextManager.Get("nomission"), font: GUI.LargeFont);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform),
|
||||||
|
TextManager.AddPunctuation(':', TextManager.Get("Mission"), displayedMission.Name), font: GUI.SubHeadingFont);
|
||||||
|
missionDescription = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform),
|
||||||
|
missionMessage, wrap: true);
|
||||||
|
if (displayedMission == selectedMission && displayedMission.Completed)
|
||||||
|
{
|
||||||
|
string rewardText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", displayedMission.Reward));
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform),
|
||||||
|
TextManager.GetWithVariable("MissionReward", "[reward]", rewardText));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ButtonArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), missionContent.RectTransform, Anchor.BottomCenter), isHorizontal: true, childAnchor: Anchor.BottomRight)
|
||||||
|
{
|
||||||
|
IgnoreLayoutGroups = true,
|
||||||
|
RelativeSpacing = 0.025f
|
||||||
|
};
|
||||||
|
|
||||||
|
ContinueButton = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), ButtonArea.RectTransform), TextManager.Get("Close"));
|
||||||
|
ButtonArea.RectTransform.NonScaledSize = new Point(ButtonArea.Rect.Width, ContinueButton.Rect.Height);
|
||||||
|
ButtonArea.RectTransform.IsFixedSize = true;
|
||||||
|
|
||||||
|
missionContent.Recalculate();
|
||||||
|
//description overlapping with the buttons -> switch to small font
|
||||||
|
if (missionDescription != null && missionDescription.Rect.Y + missionDescription.TextSize.Y > ButtonArea.Rect.Y)
|
||||||
|
{
|
||||||
|
missionDescription.Font = GUI.Style.SmallFont;
|
||||||
|
//still overlapping -> shorten the text
|
||||||
|
if (missionDescription.Rect.Y + missionDescription.TextSize.Y > ButtonArea.Rect.Y && missionDescription.WrappedText.Contains('\n'))
|
||||||
|
{
|
||||||
|
missionDescription.ToolTip = missionDescription.Text;
|
||||||
|
missionDescription.Text = missionDescription.WrappedText.Split('\n').First() + "...";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set layout -------------------------------------------------------------------
|
||||||
|
|
||||||
|
int panelSpacing = GUI.IntScale(20);
|
||||||
|
int totalHeight = crewFrame.Rect.Height + panelSpacing + missionframe.Rect.Height;
|
||||||
|
int totalWidth = crewFrame.Rect.Width;
|
||||||
|
|
||||||
|
crewFrame.RectTransform.AbsoluteOffset = new Point(0, (GameMain.GraphicsHeight - totalHeight) / 2);
|
||||||
|
missionframe.RectTransform.AbsoluteOffset = new Point(0, crewFrame.Rect.Bottom + panelSpacing);
|
||||||
|
|
||||||
|
if (rightPanels.Any())
|
||||||
|
{
|
||||||
|
totalWidth = crewFrame.Rect.Width * 2 + panelSpacing;
|
||||||
|
if (headerTextBlock != null)
|
||||||
|
{
|
||||||
|
headerTextBlock.RectTransform.MinSize = new Point(totalWidth, 0);
|
||||||
|
}
|
||||||
|
crewFrame.RectTransform.AbsoluteOffset = new Point(-(crewFrame.Rect.Width + panelSpacing) / 2, crewFrame.RectTransform.AbsoluteOffset.Y);
|
||||||
|
foreach (var rightPanel in rightPanels)
|
||||||
|
{
|
||||||
|
rightPanel.RectTransform.AbsoluteOffset = new Point((rightPanel.Rect.Width + panelSpacing) / 2, crewFrame.RectTransform.AbsoluteOffset.Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(gameSession.GameMode is CampaignMode))
|
||||||
|
{
|
||||||
|
var shadow = new GUIFrame(new RectTransform(new Point((int)(totalWidth * 1.2f), GameMain.GraphicsHeight * 2), background.RectTransform, Anchor.Center), style: "OuterGlow")
|
||||||
|
{
|
||||||
|
Color = Color.Black
|
||||||
|
};
|
||||||
|
shadow.RectTransform.SetAsFirstChild();
|
||||||
|
}
|
||||||
|
|
||||||
|
Frame = background;
|
||||||
|
return background;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetHeaderText(bool gameOver, CampaignMode.TransitionType transitionType)
|
||||||
|
{
|
||||||
|
string locationName = Submarine.MainSub.AtEndPosition ? endLocation?.Name : startLocation?.Name;
|
||||||
|
|
||||||
|
string textTag;
|
||||||
|
if (gameOver)
|
||||||
|
{
|
||||||
|
textTag = "RoundSummaryGameOver";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (transitionType)
|
||||||
|
{
|
||||||
|
case CampaignMode.TransitionType.LeaveLocation:
|
||||||
|
locationName = startLocation?.Name;
|
||||||
|
textTag = "RoundSummaryLeaving";
|
||||||
|
break;
|
||||||
|
case CampaignMode.TransitionType.ProgressToNextLocation:
|
||||||
|
case CampaignMode.TransitionType.ProgressToNextEmptyLocation:
|
||||||
|
locationName = endLocation?.Name;
|
||||||
|
textTag = "RoundSummaryProgress";
|
||||||
|
break;
|
||||||
|
case CampaignMode.TransitionType.ReturnToPreviousLocation:
|
||||||
|
case CampaignMode.TransitionType.ReturnToPreviousEmptyLocation:
|
||||||
|
locationName = startLocation?.Name;
|
||||||
|
textTag = "RoundSummaryReturn";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
textTag = Submarine.MainSub.AtEndPosition ? "RoundSummaryProgress" : "RoundSummaryReturn";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (textTag == null) { return ""; }
|
||||||
|
|
||||||
|
if (locationName == null)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError($"Error while creating round summary: could not determine destination location. Start location: {startLocation?.Name ?? "null"}, end location: {endLocation?.Name ?? "null"}");
|
||||||
|
locationName = "[UNKNOWN]";
|
||||||
|
}
|
||||||
|
|
||||||
|
string 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 });
|
||||||
|
}
|
||||||
|
|
||||||
|
private GUIListBox CreateCrewList(GUIComponent parent, IEnumerable<CharacterInfo> characterInfos)
|
||||||
|
{
|
||||||
|
var headerFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.0f), parent.RectTransform, Anchor.TopCenter, minSize: new Point(0, (int)(30 * GUI.Scale))) { }, isHorizontal: true)
|
||||||
|
{
|
||||||
|
AbsoluteSpacing = 2
|
||||||
|
};
|
||||||
|
GUIButton jobButton = new GUIButton(new RectTransform(new Vector2(0f, 1f), headerFrame.RectTransform), TextManager.Get("tabmenu.job"), style: "GUIButtonSmallFreeScale");
|
||||||
|
GUIButton characterButton = new GUIButton(new RectTransform(new Vector2(0f, 1f), headerFrame.RectTransform), TextManager.Get("name"), style: "GUIButtonSmallFreeScale");
|
||||||
|
GUIButton statusButton = new GUIButton(new RectTransform(new Vector2(0f, 1f), headerFrame.RectTransform), TextManager.Get("label.statuslabel"), style: "GUIButtonSmallFreeScale");
|
||||||
|
|
||||||
|
float sizeMultiplier = 1.0f;
|
||||||
|
//sizeMultiplier = (headerFrame.Rect.Width - headerFrame.AbsoluteSpacing * (headerFrame.CountChildren - 1)) / (float)headerFrame.Rect.Width;
|
||||||
|
|
||||||
|
jobButton.RectTransform.RelativeSize = new Vector2(jobColumnWidthPercentage * sizeMultiplier, 1f);
|
||||||
|
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.CanBeFocused = characterButton.CanBeFocused = statusButton.CanBeFocused = false;
|
||||||
|
jobButton.TextBlock.ForceUpperCase = characterButton.TextBlock.ForceUpperCase = statusButton.ForceUpperCase = true;
|
||||||
|
|
||||||
|
jobColumnWidth = jobButton.Rect.Width;
|
||||||
|
characterColumnWidth = characterButton.Rect.Width;
|
||||||
|
statusColumnWidth = statusButton.Rect.Width;
|
||||||
|
|
||||||
|
GUIListBox crewList = new GUIListBox(new RectTransform(Vector2.One, parent.RectTransform))
|
||||||
|
{
|
||||||
|
Padding = new Vector4(2, 5, 0, 0),
|
||||||
|
AutoHideScrollBar = false
|
||||||
|
};
|
||||||
|
crewList.ContentBackground.Color = Color.Transparent;
|
||||||
|
|
||||||
|
headerFrame.RectTransform.RelativeSize -= new Vector2(crewList.ScrollBar.RectTransform.RelativeSize.X, 0.0f);
|
||||||
|
|
||||||
|
foreach (CharacterInfo characterInfo in characterInfos)
|
||||||
|
{
|
||||||
|
if (characterInfo == null) { continue; }
|
||||||
|
CreateCharacterElement(characterInfo, crewList);
|
||||||
|
}
|
||||||
|
|
||||||
|
return crewList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateCharacterElement(CharacterInfo characterInfo, GUIListBox listBox)
|
||||||
|
{
|
||||||
|
GUIFrame frame = new GUIFrame(new RectTransform(new Point(listBox.Content.Rect.Width, GUI.IntScale(45)), listBox.Content.RectTransform), style: "ListBoxElement")
|
||||||
|
{
|
||||||
|
CanBeFocused = false,
|
||||||
|
UserData = characterInfo,
|
||||||
|
Color = (Character.Controlled?.Info == characterInfo) ? TabMenu.OwnCharacterBGColor : Color.Transparent
|
||||||
|
};
|
||||||
|
|
||||||
|
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.9f), frame.RectTransform, Anchor.Center), isHorizontal: true)
|
||||||
|
{
|
||||||
|
AbsoluteSpacing = 2,
|
||||||
|
Stretch = true
|
||||||
|
};
|
||||||
|
|
||||||
|
new GUICustomComponent(new RectTransform(new Point(jobColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform, Anchor.Center), onDraw: (sb, component) => characterInfo.DrawJobIcon(sb, component.Rect))
|
||||||
|
{
|
||||||
|
ToolTip = characterInfo.Job.Name ?? "",
|
||||||
|
HoverColor = Color.White,
|
||||||
|
SelectedColor = Color.White
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
string statusText = TextManager.Get("StatusOK");
|
||||||
|
Color statusColor = GUI.Style.Green;
|
||||||
|
|
||||||
|
Character character = characterInfo.Character;
|
||||||
|
if (character == null || character.IsDead)
|
||||||
|
{
|
||||||
|
if (characterInfo.IsNewHire)
|
||||||
|
{
|
||||||
|
statusText = TextManager.Get("CampaignCrew.NewHire");
|
||||||
|
statusColor = GUI.Style.Blue;
|
||||||
|
}
|
||||||
|
else if (characterInfo.CauseOfDeath == null)
|
||||||
|
{
|
||||||
|
statusText = TextManager.Get("CauseOfDeathDescription.Unknown");
|
||||||
statusColor = Color.DarkRed;
|
statusColor = Color.DarkRed;
|
||||||
}
|
}
|
||||||
|
else if (characterInfo.CauseOfDeath.Type == CauseOfDeathType.Affliction && characterInfo.CauseOfDeath.Affliction == null)
|
||||||
|
{
|
||||||
|
string errorMsg = "Character \"" + characterInfo.Name + "\" had an invalid cause of death (the type of the cause of death was Affliction, but affliction was not specified).";
|
||||||
|
DebugConsole.ThrowError(errorMsg);
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("RoundSummary:InvalidCauseOfDeath", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||||
|
statusText = TextManager.Get("CauseOfDeathDescription.Unknown");
|
||||||
|
statusColor = GUI.Style.Red;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (character.IsUnconscious)
|
statusText = characterInfo.CauseOfDeath.Type == CauseOfDeathType.Affliction ?
|
||||||
{
|
characterInfo.CauseOfDeath.Affliction.CauseOfDeathDescription :
|
||||||
statusText = TextManager.Get("Unconscious");
|
TextManager.Get("CauseOfDeathDescription." + characterInfo.CauseOfDeath.Type.ToString());
|
||||||
statusColor = Color.DarkOrange;
|
statusColor = Color.DarkRed;
|
||||||
}
|
}
|
||||||
else if (character.Vitality / character.MaxVitality < 0.8f)
|
}
|
||||||
{
|
else
|
||||||
statusText = TextManager.Get("Injured");
|
{
|
||||||
statusColor = Color.DarkOrange;
|
if (character.IsUnconscious)
|
||||||
}
|
{
|
||||||
|
statusText = TextManager.Get("Unconscious");
|
||||||
|
statusColor = Color.DarkOrange;
|
||||||
|
}
|
||||||
|
else if (character.Vitality / character.MaxVitality < 0.8f)
|
||||||
|
{
|
||||||
|
statusText = TextManager.Get("Injured");
|
||||||
|
statusColor = Color.DarkOrange;
|
||||||
}
|
}
|
||||||
|
|
||||||
var textHolder = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), characterFrame.RectTransform, Anchor.BottomCenter), style: "InnerGlow", color: statusColor);
|
|
||||||
new GUITextBlock(new RectTransform(Vector2.One, textHolder.RectTransform, Anchor.Center),
|
|
||||||
statusText, Color.White,
|
|
||||||
textAlignment: Alignment.Center,
|
|
||||||
wrap: true, font: GUI.SmallFont, style: null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), paddedFrame.RectTransform), isHorizontal: true, childAnchor: Anchor.BottomRight)
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateReputationElement(GUIComponent parent,
|
||||||
|
string name, float reputation, float normalizedReputation, float initialReputation,
|
||||||
|
string shortDescription, string fullDescription, Sprite icon, Sprite backgroundPortrait, Color iconColor)
|
||||||
|
{
|
||||||
|
var factionFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.3f), parent.RectTransform), style: null);
|
||||||
|
|
||||||
|
if (backgroundPortrait != null)
|
||||||
{
|
{
|
||||||
RelativeSpacing = 0.05f,
|
new GUICustomComponent(new RectTransform(Vector2.One, factionFrame.RectTransform), onDraw: (sb, customComponent) =>
|
||||||
UserData = "buttonarea"
|
{
|
||||||
|
backgroundPortrait.Draw(sb, customComponent.Rect.Center.ToVector2(), customComponent.Color, backgroundPortrait.size / 2, scale: customComponent.Rect.Width / backgroundPortrait.size.X);
|
||||||
|
})
|
||||||
|
{
|
||||||
|
HideElementsOutsideFrame = true,
|
||||||
|
IgnoreLayoutGroups = true,
|
||||||
|
Color = iconColor * 0.2f
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var factionInfoHorizontal = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), factionFrame.RectTransform, Anchor.Center), childAnchor: Anchor.CenterLeft, isHorizontal: true)
|
||||||
|
{
|
||||||
|
RelativeSpacing = 0.02f,
|
||||||
|
Stretch = true
|
||||||
};
|
};
|
||||||
|
|
||||||
paddedFrame.Recalculate();
|
var factionTextContent = new GUILayoutGroup(new RectTransform(Vector2.One, factionInfoHorizontal.RectTransform))
|
||||||
foreach (GUIComponent child in infoTextBox.Content.Children)
|
|
||||||
{
|
{
|
||||||
child.CanBeFocused = false;
|
RelativeSpacing = 0.05f,
|
||||||
if (child is GUITextBlock textBlock)
|
Stretch = true
|
||||||
{
|
};
|
||||||
textBlock.CalculateHeightFromText();
|
var factionIcon = new GUIImage(new RectTransform(new Point((int)(factionInfoHorizontal.Rect.Height * 0.7f)), factionInfoHorizontal.RectTransform, scaleBasis: ScaleBasis.Smallest), icon, scaleToFit: true)
|
||||||
}
|
{
|
||||||
|
Color = iconColor
|
||||||
|
};
|
||||||
|
factionInfoHorizontal.Recalculate();
|
||||||
|
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), factionTextContent.RectTransform),
|
||||||
|
name, font: GUI.SubHeadingFont)
|
||||||
|
{
|
||||||
|
Padding = Vector4.Zero
|
||||||
|
};
|
||||||
|
var factionDescription = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.6f), factionTextContent.RectTransform),
|
||||||
|
shortDescription, font: GUI.SmallFont, wrap: true)
|
||||||
|
{
|
||||||
|
UserData = "description",
|
||||||
|
Padding = Vector4.Zero
|
||||||
|
};
|
||||||
|
if (shortDescription != fullDescription && !string.IsNullOrEmpty(fullDescription))
|
||||||
|
{
|
||||||
|
factionDescription.ToolTip = fullDescription;
|
||||||
}
|
}
|
||||||
|
|
||||||
return frame;
|
var sliderHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), factionTextContent.RectTransform),
|
||||||
|
childAnchor: Anchor.CenterLeft, isHorizontal: true)
|
||||||
|
{
|
||||||
|
RelativeSpacing = 0.05f,
|
||||||
|
Stretch = true
|
||||||
|
};
|
||||||
|
sliderHolder.RectTransform.MaxSize = new Point(int.MaxValue, GUI.IntScale(25.0f));
|
||||||
|
factionTextContent.Recalculate();
|
||||||
|
|
||||||
|
new GUICustomComponent(new RectTransform(new Vector2(0.8f, 1.0f), sliderHolder.RectTransform), onDraw: (sb, customComponent) =>
|
||||||
|
{
|
||||||
|
GUI.DrawRectangle(sb, customComponent.Rect, GUI.Style.ColorInventoryBackground, isFilled: true);
|
||||||
|
if (normalizedReputation < 0.5f)
|
||||||
|
{
|
||||||
|
int barWidth = (int)((0.5f - normalizedReputation) * customComponent.Rect.Width);
|
||||||
|
GUI.DrawRectangle(sb, new Rectangle(customComponent.Rect.Center.X - barWidth, customComponent.Rect.Y, barWidth, customComponent.Rect.Height), GUI.Style.Red, isFilled: true);
|
||||||
|
}
|
||||||
|
else if (normalizedReputation > 0.5f)
|
||||||
|
{
|
||||||
|
int barWidth = (int)((normalizedReputation - 0.5f) * customComponent.Rect.Width);
|
||||||
|
GUI.DrawRectangle(sb, new Rectangle(customComponent.Rect.Center.X, customComponent.Rect.Y, barWidth, customComponent.Rect.Height), GUI.Style.Green, isFilled: true);
|
||||||
|
}
|
||||||
|
GUI.DrawLine(sb, new Vector2(customComponent.Rect.Center.X, customComponent.Rect.Y - 2), new Vector2(customComponent.Rect.Center.X, customComponent.Rect.Bottom + 2), factionDescription.TextColor, width: 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
string reputationText = ((int)Math.Round(reputation)).ToString();
|
||||||
|
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);
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), sliderHolder.RectTransform),
|
||||||
|
rtData, sanitizedText,
|
||||||
|
textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), sliderHolder.RectTransform),
|
||||||
|
reputationText,
|
||||||
|
textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Barotrauma.Networking;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
partial class UpgradeManager
|
||||||
|
{
|
||||||
|
partial void UpgradeNPCSpeak(string text, bool isSinglePlayer, Character? character)
|
||||||
|
{
|
||||||
|
if (Level.Loaded?.StartOutpost?.Info?.OutpostNPCs == null) { return; }
|
||||||
|
|
||||||
|
if (character != null)
|
||||||
|
{
|
||||||
|
Speak(character);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Character npc in Level.Loaded.StartOutpost.Info.OutpostNPCs.SelectMany(kpv => kpv.Value))
|
||||||
|
{
|
||||||
|
if (npc.CampaignInteractionType == CampaignMode.InteractionType.Upgrade)
|
||||||
|
{
|
||||||
|
Speak(npc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Speak(Character npc)
|
||||||
|
{
|
||||||
|
ChatMessage message = ChatMessage.Create(npc.Name, text, ChatMessageType.Default, npc);
|
||||||
|
if (!isSinglePlayer)
|
||||||
|
{
|
||||||
|
GameMain.Client?.AddChatMessage(message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GameMain.GameSession?.CrewManager?.AddSinglePlayerChatMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Server has notified us that upgrades were reset.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inc"></param>
|
||||||
|
/// <see cref="UpgradeManager.SendUpgradeResetMessage"/>
|
||||||
|
public void ClientRead(IReadMessage inc)
|
||||||
|
{
|
||||||
|
bool shouldReset = inc.ReadBoolean();
|
||||||
|
int money = inc.ReadInt32();
|
||||||
|
// uint length = inc.ReadUInt32();
|
||||||
|
//
|
||||||
|
// for (int i = 0; i < length; i++)
|
||||||
|
// {
|
||||||
|
// string key = inc.ReadString();
|
||||||
|
// byte value = inc.ReadByte();
|
||||||
|
// Metadata.SetValue(key, value);
|
||||||
|
// }
|
||||||
|
|
||||||
|
Campaign.Money = money;
|
||||||
|
|
||||||
|
if (shouldReset)
|
||||||
|
{
|
||||||
|
ResetUpgrades();
|
||||||
|
}
|
||||||
|
|
||||||
|
// spentMoney is local, so this message box should only appear for those who have spent money on upgrades
|
||||||
|
if (spentMoney > 0)
|
||||||
|
{
|
||||||
|
GUIMessageBox msgBox = new GUIMessageBox(TextManager.Get("UpgradeRefundTitle"), TextManager.Get("UpgradeRefundBody"), new [] { TextManager.Get("Ok") });
|
||||||
|
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
||||||
|
}
|
||||||
|
|
||||||
|
spentMoney = 0;
|
||||||
|
PendingUpgrades.Clear();
|
||||||
|
PurchasedUpgrades.Clear();
|
||||||
|
CanUpgrade = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -761,6 +761,44 @@ namespace Barotrauma
|
|||||||
RelativeSpacing = 0.01f
|
RelativeSpacing = 0.01f
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if (!OSX)
|
||||||
|
AudioDeviceNames = Alc.GetStringList((IntPtr)null, Alc.AllDevicesSpecifier);
|
||||||
|
if (string.IsNullOrEmpty(AudioOutputDevice))
|
||||||
|
{
|
||||||
|
AudioOutputDevice = Alc.GetString((IntPtr)null, Alc.DefaultDeviceSpecifier);
|
||||||
|
if (AudioDeviceNames.Any() && !AudioDeviceNames.Any(n => n.Equals(AudioOutputDevice, StringComparison.OrdinalIgnoreCase)))
|
||||||
|
{
|
||||||
|
AudioOutputDevice = AudioDeviceNames[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var outputDeviceList = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.15f), audioContent.RectTransform), TrimAudioDeviceName(AudioOutputDevice), AudioDeviceNames.Count);
|
||||||
|
if (AudioDeviceNames?.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (string name in AudioDeviceNames)
|
||||||
|
{
|
||||||
|
outputDeviceList.AddItem(TrimAudioDeviceName(name), name);
|
||||||
|
}
|
||||||
|
outputDeviceList.OnSelected = (GUIComponent selected, object obj) =>
|
||||||
|
{
|
||||||
|
string name = obj as string;
|
||||||
|
if (!GameMain.SoundManager.Disconnected && AudioOutputDevice == name) { return true; }
|
||||||
|
|
||||||
|
AudioOutputDevice = name;
|
||||||
|
GameMain.SoundManager.InitializeAlcDevice(AudioOutputDevice);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outputDeviceList.AddItem(TextManager.Get("AudioNoDevices") ?? "N/A", null);
|
||||||
|
outputDeviceList.ButtonTextColor = GUI.Style.Red;
|
||||||
|
outputDeviceList.ButtonEnabled = false;
|
||||||
|
outputDeviceList.Select(0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
GUITextBlock soundVolumeText = new GUITextBlock(new RectTransform(textBlockScale, audioContent.RectTransform), TextManager.Get("SoundVolume"), font: GUI.SubHeadingFont);
|
GUITextBlock soundVolumeText = new GUITextBlock(new RectTransform(textBlockScale, audioContent.RectTransform), TextManager.Get("SoundVolume"), font: GUI.SubHeadingFont);
|
||||||
GUIScrollBar soundScrollBar = new GUIScrollBar(new RectTransform(textBlockScale, audioContent.RectTransform),
|
GUIScrollBar soundScrollBar = new GUIScrollBar(new RectTransform(textBlockScale, audioContent.RectTransform),
|
||||||
style: "GUISlider", barSize: 0.05f)
|
style: "GUISlider", barSize: 0.05f)
|
||||||
@@ -893,7 +931,7 @@ namespace Barotrauma
|
|||||||
deviceList.OnSelected = (GUIComponent selected, object obj) =>
|
deviceList.OnSelected = (GUIComponent selected, object obj) =>
|
||||||
{
|
{
|
||||||
string name = obj as string;
|
string name = obj as string;
|
||||||
if (VoiceCaptureDevice == name) { return true; }
|
if (!(VoipCapture.Instance?.Disconnected ?? true) && VoiceCaptureDevice == name) { return true; }
|
||||||
|
|
||||||
VoipCapture.ChangeCaptureDevice(name);
|
VoipCapture.ChangeCaptureDevice(name);
|
||||||
return true;
|
return true;
|
||||||
@@ -1179,12 +1217,16 @@ namespace Barotrauma
|
|||||||
var inputName = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), inputContainer.RectTransform, Anchor.TopLeft) { MinSize = new Point(100, 0) },
|
var inputName = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), inputContainer.RectTransform, Anchor.TopLeft) { MinSize = new Point(100, 0) },
|
||||||
TextManager.Get("InputType." + ((InputType)i)), font: GUI.SmallFont) { ForceUpperCase = true };
|
TextManager.Get("InputType." + ((InputType)i)), font: GUI.SmallFont) { ForceUpperCase = true };
|
||||||
inputNameBlocks.Add(inputName);
|
inputNameBlocks.Add(inputName);
|
||||||
|
string keyText = KeyBindText((InputType)i);
|
||||||
var keyBox = new GUITextBox(new RectTransform(new Vector2(0.4f, 1.0f), inputContainer.RectTransform),
|
var keyBox = new GUITextBox(new RectTransform(new Vector2(0.4f, 1.0f), inputContainer.RectTransform),
|
||||||
text: KeyBindText((InputType)i), font: GUI.SmallFont, style: "GUITextBoxNoIcon")
|
text: keyText, font: GUI.SmallFont, style: "GUITextBoxNoIcon")
|
||||||
{
|
{
|
||||||
UserData = i
|
UserData = i
|
||||||
};
|
};
|
||||||
keyBox.Text = ToolBox.LimitString(keyBox.Text, keyBox.Font, (int)(keyBox.Rect.Width - keyBox.Padding.X - keyBox.Padding.Z));
|
keyBox.RectTransform.SizeChanged += () =>
|
||||||
|
{
|
||||||
|
keyBox.Text = ToolBox.LimitString(keyText, keyBox.Font, (int)(keyBox.Rect.Width - keyBox.Padding.X - keyBox.Padding.Z));
|
||||||
|
};
|
||||||
keyBox.OnSelected += KeyBoxSelected;
|
keyBox.OnSelected += KeyBoxSelected;
|
||||||
keyBox.SelectedColor = Color.Gold * 0.3f;
|
keyBox.SelectedColor = Color.Gold * 0.3f;
|
||||||
}
|
}
|
||||||
@@ -1337,6 +1379,16 @@ namespace Barotrauma
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var automaticCampaignLoadTickBox = new GUITickBox(new RectTransform(tickBoxScale / 0.18f, debugTickBoxes.RectTransform, scaleBasis: ScaleBasis.BothHeight), "Automatic campaign load enabled", style: "GUITickBox");
|
||||||
|
automaticCampaignLoadTickBox.Selected = AutomaticCampaignLoadEnabled;
|
||||||
|
automaticCampaignLoadTickBox.ToolTip = "Will the game automatically load the latest campaign save when the game is launched";
|
||||||
|
automaticCampaignLoadTickBox.OnSelected = (tickBox) =>
|
||||||
|
{
|
||||||
|
AutomaticCampaignLoadEnabled = tickBox.Selected;
|
||||||
|
UnsavedSettings = true;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
var showSplashScreenTickBox = new GUITickBox(new RectTransform(tickBoxScale / 0.18f, debugTickBoxes.RectTransform, scaleBasis: ScaleBasis.BothHeight), "Splash screen enabled", style: "GUITickBox");
|
var showSplashScreenTickBox = new GUITickBox(new RectTransform(tickBoxScale / 0.18f, debugTickBoxes.RectTransform, scaleBasis: ScaleBasis.BothHeight), "Splash screen enabled", style: "GUITickBox");
|
||||||
showSplashScreenTickBox.Selected = EnableSplashScreen;
|
showSplashScreenTickBox.Selected = EnableSplashScreen;
|
||||||
showSplashScreenTickBox.ToolTip = "Are the splash screens shown when the game is launched";
|
showSplashScreenTickBox.ToolTip = "Are the splash screens shown when the game is launched";
|
||||||
@@ -1520,8 +1572,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
return GameMain.Client == null &&
|
return GameMain.Client == null &&
|
||||||
(ContentPackage.IngameModSwap ||
|
(ContentPackage.IngameModSwap ||
|
||||||
(Screen.Selected != GameMain.GameScreen &&
|
Screen.Selected != GameMain.GameScreen &&
|
||||||
Screen.Selected != GameMain.LobbyScreen) &&
|
|
||||||
Screen.Selected != GameMain.SubEditorScreen) &&
|
Screen.Selected != GameMain.SubEditorScreen) &&
|
||||||
(!core ||
|
(!core ||
|
||||||
(Screen.Selected != GameMain.CharacterEditorScreen &&
|
(Screen.Selected != GameMain.CharacterEditorScreen &&
|
||||||
|
|||||||
@@ -35,6 +35,26 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static Dictionary<InvSlotType, Sprite> limbSlotIcons;
|
private static Dictionary<InvSlotType, Sprite> limbSlotIcons;
|
||||||
|
public static Dictionary<InvSlotType, Sprite> LimbSlotIcons
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (limbSlotIcons == null)
|
||||||
|
{
|
||||||
|
limbSlotIcons = new Dictionary<InvSlotType, Sprite>();
|
||||||
|
int margin = 2;
|
||||||
|
limbSlotIcons.Add(InvSlotType.Headset, new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(384 + margin, 128 + margin, 128 - margin * 2, 128 - margin * 2)));
|
||||||
|
limbSlotIcons.Add(InvSlotType.InnerClothes, new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(512 + margin, 128 + margin, 128 - margin * 2, 128 - margin * 2)));
|
||||||
|
limbSlotIcons.Add(InvSlotType.Card, new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(640 + margin, 128 + margin, 128 - margin * 2, 128 - margin * 2)));
|
||||||
|
|
||||||
|
limbSlotIcons.Add(InvSlotType.Head, new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(896 + margin, 128 + margin, 128 - margin * 2, 128 - margin * 2)));
|
||||||
|
limbSlotIcons.Add(InvSlotType.LeftHand, new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(634, 0, 128, 128)));
|
||||||
|
limbSlotIcons.Add(InvSlotType.RightHand, new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(762, 0, 128, 128)));
|
||||||
|
limbSlotIcons.Add(InvSlotType.OuterClothes, new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(256 + margin, 128 + margin, 128 - margin * 2, 128 - margin * 2)));
|
||||||
|
}
|
||||||
|
return limbSlotIcons;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public const InvSlotType PersonalSlots = InvSlotType.Card | InvSlotType.Headset | InvSlotType.InnerClothes | InvSlotType.OuterClothes | InvSlotType.Head;
|
public const InvSlotType PersonalSlots = InvSlotType.Card | InvSlotType.Headset | InvSlotType.InnerClothes | InvSlotType.OuterClothes | InvSlotType.Head;
|
||||||
|
|
||||||
@@ -88,7 +108,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
indicatorGroup = new GUILayoutGroup(new RectTransform(Point.Zero, hideButton.RectTransform)) { IsHorizontal = false };
|
indicatorGroup = new GUILayoutGroup(new RectTransform(Point.Zero, hideButton.RectTransform)) { IsHorizontal = false };
|
||||||
indicatorGroup.ChildAnchor = Anchor.TopCenter;
|
indicatorGroup.ChildAnchor = Anchor.TopCenter;
|
||||||
indicatorSpriteSize = GUI.Style.GetComponentStyle("EquipmentIndicatorDivingSuit").Sprites[GUIComponent.ComponentState.None][0].Sprite.size;
|
indicatorSpriteSize = GUI.Style.GetComponentStyle("EquipmentIndicatorDivingSuit").GetDefaultSprite().size;
|
||||||
|
|
||||||
indicators[0] = new GUIImage(new RectTransform(Point.Zero, indicatorGroup.RectTransform), "EquipmentIndicatorDivingSuit");
|
indicators[0] = new GUIImage(new RectTransform(Point.Zero, indicatorGroup.RectTransform), "EquipmentIndicatorDivingSuit");
|
||||||
indicators[1] = new GUIImage(new RectTransform(Point.Zero, indicatorGroup.RectTransform), "EquipmentIndicatorID");
|
indicators[1] = new GUIImage(new RectTransform(Point.Zero, indicatorGroup.RectTransform), "EquipmentIndicatorID");
|
||||||
@@ -115,20 +135,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
hidePersonalSlots = false;
|
hidePersonalSlots = false;
|
||||||
|
|
||||||
if (limbSlotIcons == null)
|
|
||||||
{
|
|
||||||
limbSlotIcons = new Dictionary<InvSlotType, Sprite>();
|
|
||||||
|
|
||||||
int margin = 2;
|
|
||||||
limbSlotIcons.Add(InvSlotType.Headset, new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(384 + margin, 128 + margin, 128 - margin * 2, 128 - margin * 2)));
|
|
||||||
limbSlotIcons.Add(InvSlotType.InnerClothes, new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(512 + margin, 128 + margin, 128 - margin * 2, 128 - margin * 2)));
|
|
||||||
limbSlotIcons.Add(InvSlotType.Card, new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(640 + margin, 128 + margin, 128 - margin * 2, 128 - margin * 2)));
|
|
||||||
|
|
||||||
limbSlotIcons.Add(InvSlotType.Head, new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(896 + margin, 128 + margin, 128 - margin * 2, 128 - margin * 2)));
|
|
||||||
limbSlotIcons.Add(InvSlotType.LeftHand, new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(634, 0, 128, 128)));
|
|
||||||
limbSlotIcons.Add(InvSlotType.RightHand, new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(762, 0, 128, 128)));
|
|
||||||
limbSlotIcons.Add(InvSlotType.OuterClothes, new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(256 + margin, 128 + margin, 128 - margin * 2, 128 - margin * 2)));
|
|
||||||
}
|
|
||||||
SlotPositions = new Vector2[SlotTypes.Length];
|
SlotPositions = new Vector2[SlotTypes.Length];
|
||||||
CurrentLayout = Layout.Default;
|
CurrentLayout = Layout.Default;
|
||||||
SetSlotPositions(layout);
|
SetSlotPositions(layout);
|
||||||
@@ -522,14 +528,7 @@ namespace Barotrauma
|
|||||||
if (hoverOnInventory) { HideTimer = 0.5f; }
|
if (hoverOnInventory) { HideTimer = 0.5f; }
|
||||||
if (HideTimer > 0.0f) { HideTimer -= deltaTime; }
|
if (HideTimer > 0.0f) { HideTimer -= deltaTime; }
|
||||||
|
|
||||||
for (int i = 0; i < capacity; i++)
|
UpdateSlotInput();
|
||||||
{
|
|
||||||
if (Items[i] != null && Items[i] != draggingItem && Character.Controlled?.Inventory == this &&
|
|
||||||
GUI.KeyboardDispatcher.Subscriber == null && !CrewManager.IsCommandInterfaceOpen && PlayerInput.InventoryKeyHit(slots[i].InventoryKeyIndex))
|
|
||||||
{
|
|
||||||
QuickUseItem(Items[i], true, false, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//force personal slots open if an item is running out of battery/fuel/oxygen/etc
|
//force personal slots open if an item is running out of battery/fuel/oxygen/etc
|
||||||
if (hidePersonalSlots)
|
if (hidePersonalSlots)
|
||||||
@@ -685,6 +684,18 @@ namespace Barotrauma
|
|||||||
doubleClickedItem = null;
|
doubleClickedItem = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void UpdateSlotInput()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < capacity; i++)
|
||||||
|
{
|
||||||
|
if (Items[i] != null && Items[i] != draggingItem && Character.Controlled?.Inventory == this &&
|
||||||
|
GUI.KeyboardDispatcher.Subscriber == null && !CrewManager.IsCommandInterfaceOpen && PlayerInput.InventoryKeyHit(slots[i].InventoryKeyIndex))
|
||||||
|
{
|
||||||
|
QuickUseItem(Items[i], true, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void HandleButtonEquipStates(Item item, InventorySlot slot, float deltaTime)
|
private void HandleButtonEquipStates(Item item, InventorySlot slot, float deltaTime)
|
||||||
{
|
{
|
||||||
slot.EquipButtonState = slot.EquipButtonRect.Contains(PlayerInput.MousePosition) ?
|
slot.EquipButtonState = slot.EquipButtonRect.Contains(PlayerInput.MousePosition) ?
|
||||||
@@ -1084,9 +1095,9 @@ namespace Barotrauma
|
|||||||
!Items[i].AllowedSlots.Any(a => a != InvSlotType.Any))
|
!Items[i].AllowedSlots.Any(a => a != InvSlotType.Any))
|
||||||
{
|
{
|
||||||
//draw limb icons on empty slots
|
//draw limb icons on empty slots
|
||||||
if (limbSlotIcons.ContainsKey(SlotTypes[i]))
|
if (LimbSlotIcons.ContainsKey(SlotTypes[i]))
|
||||||
{
|
{
|
||||||
var icon = limbSlotIcons[SlotTypes[i]];
|
var icon = LimbSlotIcons[SlotTypes[i]];
|
||||||
icon.Draw(spriteBatch, slots[i].Rect.Center.ToVector2() + slots[i].DrawOffset, GUI.Style.EquipmentSlotIconColor, origin: icon.size / 2, scale: slots[i].Rect.Width / icon.size.X);
|
icon.Draw(spriteBatch, slots[i].Rect.Center.ToVector2() + slots[i].DrawOffset, GUI.Style.EquipmentSlotIconColor, origin: icon.size / 2, scale: slots[i].Rect.Width / icon.size.X);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@@ -1096,12 +1107,12 @@ namespace Barotrauma
|
|||||||
//draw hand icons if the item is equipped in a hand slot
|
//draw hand icons if the item is equipped in a hand slot
|
||||||
if (IsInLimbSlot(Items[i], InvSlotType.LeftHand))
|
if (IsInLimbSlot(Items[i], InvSlotType.LeftHand))
|
||||||
{
|
{
|
||||||
var icon = limbSlotIcons[InvSlotType.LeftHand];
|
var icon = LimbSlotIcons[InvSlotType.LeftHand];
|
||||||
icon.Draw(spriteBatch, new Vector2(slots[i].Rect.X, slots[i].Rect.Bottom) + slots[i].DrawOffset, Color.White * 0.6f, origin: new Vector2(icon.size.X * 0.35f, icon.size.Y * 0.75f), scale: slots[i].Rect.Width / icon.size.X * 0.7f);
|
icon.Draw(spriteBatch, new Vector2(slots[i].Rect.X, slots[i].Rect.Bottom) + slots[i].DrawOffset, Color.White * 0.6f, origin: new Vector2(icon.size.X * 0.35f, icon.size.Y * 0.75f), scale: slots[i].Rect.Width / icon.size.X * 0.7f);
|
||||||
}
|
}
|
||||||
if (IsInLimbSlot(Items[i], InvSlotType.RightHand))
|
if (IsInLimbSlot(Items[i], InvSlotType.RightHand))
|
||||||
{
|
{
|
||||||
var icon = limbSlotIcons[InvSlotType.RightHand];
|
var icon = LimbSlotIcons[InvSlotType.RightHand];
|
||||||
icon.Draw(spriteBatch, new Vector2(slots[i].Rect.Right, slots[i].Rect.Bottom) + slots[i].DrawOffset, Color.White * 0.6f, origin: new Vector2(icon.size.X * 0.65f, icon.size.Y * 0.75f), scale: slots[i].Rect.Width / icon.size.X * 0.7f);
|
icon.Draw(spriteBatch, new Vector2(slots[i].Rect.Right, slots[i].Rect.Bottom) + slots[i].DrawOffset, Color.White * 0.6f, origin: new Vector2(icon.size.X * 0.65f, icon.size.Y * 0.75f), scale: slots[i].Rect.Width / icon.size.X * 0.7f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private void UpdateConvexHulls()
|
private void UpdateConvexHulls()
|
||||||
{
|
{
|
||||||
|
if (item.Removed) { return; }
|
||||||
|
|
||||||
doorRect = new Rectangle(
|
doorRect = new Rectangle(
|
||||||
item.Rect.Center.X - (int)(doorSprite.size.X / 2 * item.Scale),
|
item.Rect.Center.X - (int)(doorSprite.size.X / 2 * item.Scale),
|
||||||
item.Rect.Y - item.Rect.Height / 2 + (int)(doorSprite.size.Y / 2.0f * item.Scale),
|
item.Rect.Y - item.Rect.Height / 2 + (int)(doorSprite.size.Y / 2.0f * item.Scale),
|
||||||
@@ -93,7 +95,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (convexHull == null) return;
|
if (convexHull == null) { return; }
|
||||||
|
|
||||||
if (rect.Height == 0 || rect.Width == 0)
|
if (rect.Height == 0 || rect.Width == 0)
|
||||||
{
|
{
|
||||||
@@ -128,7 +130,7 @@ namespace Barotrauma.Items.Components
|
|||||||
if (brokenSprite == null)
|
if (brokenSprite == null)
|
||||||
{
|
{
|
||||||
//broken doors turn black if no broken sprite has been configured
|
//broken doors turn black if no broken sprite has been configured
|
||||||
color *= (item.Condition / item.Prefab.Health);
|
color *= (item.Condition / item.MaxCondition);
|
||||||
color.A = 255;
|
color.A = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,10 +164,10 @@ namespace Barotrauma.Items.Components
|
|||||||
color, 0.0f, doorSprite.Origin, item.Scale, SpriteEffects.None, doorSprite.Depth);
|
color, 0.0f, doorSprite.Origin, item.Scale, SpriteEffects.None, doorSprite.Depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (brokenSprite != null && item.Health < item.Prefab.Health)
|
if (brokenSprite != null && item.Health < item.MaxCondition)
|
||||||
{
|
{
|
||||||
Vector2 scale = scaleBrokenSprite ? new Vector2(1.0f, 1.0f - item.Health / item.Prefab.Health) : Vector2.One;
|
Vector2 scale = scaleBrokenSprite ? new Vector2(1.0f, 1.0f - item.Health / item.MaxCondition) : Vector2.One;
|
||||||
float alpha = fadeBrokenSprite ? 1.0f - item.Health / item.Prefab.Health : 1.0f;
|
float alpha = fadeBrokenSprite ? 1.0f - item.Health / item.MaxCondition : 1.0f;
|
||||||
spriteBatch.Draw(brokenSprite.Texture, pos,
|
spriteBatch.Draw(brokenSprite.Texture, pos,
|
||||||
new Rectangle((int)(brokenSprite.SourceRect.X + brokenSprite.size.X * openState), brokenSprite.SourceRect.Y,
|
new Rectangle((int)(brokenSprite.SourceRect.X + brokenSprite.size.X * openState), brokenSprite.SourceRect.Y,
|
||||||
(int)(brokenSprite.size.X * (1.0f - openState)), (int)brokenSprite.size.Y),
|
(int)(brokenSprite.size.X * (1.0f - openState)), (int)brokenSprite.size.Y),
|
||||||
@@ -188,10 +190,10 @@ namespace Barotrauma.Items.Components
|
|||||||
color, 0.0f, doorSprite.Origin, item.Scale, SpriteEffects.None, doorSprite.Depth);
|
color, 0.0f, doorSprite.Origin, item.Scale, SpriteEffects.None, doorSprite.Depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (brokenSprite != null && item.Health < item.Prefab.Health)
|
if (brokenSprite != null && item.Health < item.MaxCondition)
|
||||||
{
|
{
|
||||||
Vector2 scale = scaleBrokenSprite ? new Vector2(1.0f - item.Health / item.Prefab.Health, 1.0f) : Vector2.One;
|
Vector2 scale = scaleBrokenSprite ? new Vector2(1.0f - item.Health / item.MaxCondition, 1.0f) : Vector2.One;
|
||||||
float alpha = fadeBrokenSprite ? 1.0f - item.Health / item.Prefab.Health : 1.0f;
|
float alpha = fadeBrokenSprite ? 1.0f - item.Health / item.MaxCondition : 1.0f;
|
||||||
spriteBatch.Draw(brokenSprite.Texture, pos,
|
spriteBatch.Draw(brokenSprite.Texture, pos,
|
||||||
new Rectangle(brokenSprite.SourceRect.X, (int)(brokenSprite.SourceRect.Y + brokenSprite.size.Y * openState),
|
new Rectangle(brokenSprite.SourceRect.X, (int)(brokenSprite.SourceRect.Y + brokenSprite.size.Y * openState),
|
||||||
(int)brokenSprite.size.X, (int)(brokenSprite.size.Y * (1.0f - openState))),
|
(int)brokenSprite.size.X, (int)(brokenSprite.size.Y * (1.0f - openState))),
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
protected override void RemoveComponentSpecific()
|
protected override void RemoveComponentSpecific()
|
||||||
{
|
{
|
||||||
|
base.RemoveComponentSpecific();
|
||||||
crosshairSprite?.Remove();
|
crosshairSprite?.Remove();
|
||||||
crosshairSprite = null;
|
crosshairSprite = null;
|
||||||
crosshairPointerSprite?.Remove();
|
crosshairPointerSprite?.Remove();
|
||||||
|
|||||||
@@ -186,7 +186,6 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private bool shouldMuffleLooping;
|
private bool shouldMuffleLooping;
|
||||||
private float lastMuffleCheckTime;
|
private float lastMuffleCheckTime;
|
||||||
private ItemSound loopingSound;
|
private ItemSound loopingSound;
|
||||||
@@ -295,8 +294,6 @@ namespace Barotrauma.Items.Components
|
|||||||
PlaySound(matchingSounds[index], item.WorldPosition);
|
PlaySound(matchingSounds[index], item.WorldPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void PlaySound(ItemSound itemSound, Vector2 position)
|
private void PlaySound(ItemSound itemSound, Vector2 position)
|
||||||
{
|
{
|
||||||
if (Vector2.DistanceSquared(new Vector2(GameMain.SoundManager.ListenerPosition.X, GameMain.SoundManager.ListenerPosition.Y), position) > itemSound.Range * itemSound.Range)
|
if (Vector2.DistanceSquared(new Vector2(GameMain.SoundManager.ListenerPosition.X, GameMain.SoundManager.ListenerPosition.Y), position) > itemSound.Range * itemSound.Range)
|
||||||
@@ -387,7 +384,6 @@ namespace Barotrauma.Items.Components
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ItemComponent GetLinkUIToComponent()
|
public ItemComponent GetLinkUIToComponent()
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(LinkUIToComponent))
|
if (string.IsNullOrEmpty(LinkUIToComponent))
|
||||||
@@ -431,13 +427,8 @@ namespace Barotrauma.Items.Components
|
|||||||
DebugConsole.ThrowError("Error in item config \"" + item.ConfigFile + "\" - GUIFrame defined as rect, use RectTransform instead.");
|
DebugConsole.ThrowError("Error in item config \"" + item.ConfigFile + "\" - GUIFrame defined as rect, use RectTransform instead.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
GuiFrameSource = subElement;
|
||||||
Color? color = null;
|
ReloadGuiFrame();
|
||||||
if (subElement.Attribute("color") != null) color = subElement.GetAttributeColor("color", Color.White);
|
|
||||||
string style = subElement.Attribute("style") == null ?
|
|
||||||
null : subElement.GetAttributeString("style", "");
|
|
||||||
GuiFrame = new GUIFrame(RectTransform.Load(subElement, GUI.Canvas.ItemComponentHolder, Anchor.Center), style, color);
|
|
||||||
DefaultLayout = GUILayoutSettings.Load(subElement);
|
|
||||||
break;
|
break;
|
||||||
case "alternativelayout":
|
case "alternativelayout":
|
||||||
AlternativeLayout = GUILayoutSettings.Load(subElement);
|
AlternativeLayout = GUILayoutSettings.Load(subElement);
|
||||||
@@ -501,6 +492,42 @@ namespace Barotrauma.Items.Components
|
|||||||
return true; //element processed
|
return true; //element processed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private XElement GuiFrameSource;
|
||||||
|
|
||||||
|
protected void ReleaseGuiFrame()
|
||||||
|
{
|
||||||
|
if (GuiFrame != null)
|
||||||
|
{
|
||||||
|
GuiFrame.RectTransform.Parent = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void ReloadGuiFrame()
|
||||||
|
{
|
||||||
|
if (GuiFrame != null)
|
||||||
|
{
|
||||||
|
ReleaseGuiFrame();
|
||||||
|
}
|
||||||
|
Color? color = null;
|
||||||
|
if (GuiFrameSource.Attribute("color") != null)
|
||||||
|
{
|
||||||
|
color = GuiFrameSource.GetAttributeColor("color", Color.White);
|
||||||
|
}
|
||||||
|
string style = GuiFrameSource.Attribute("style") == null ? null : GuiFrameSource.GetAttributeString("style", "");
|
||||||
|
GuiFrame = new GUIFrame(RectTransform.Load(GuiFrameSource, GUI.Canvas.ItemComponentHolder, Anchor.Center), style, color);
|
||||||
|
DefaultLayout = GUILayoutSettings.Load(GuiFrameSource);
|
||||||
|
if (GuiFrame != null)
|
||||||
|
{
|
||||||
|
GuiFrame.RectTransform.ParentChanged += OnGUIParentChanged;
|
||||||
|
}
|
||||||
|
GameMain.Instance.ResolutionChanged += OnResolutionChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Overload this method and implement. The method is automatically called when the resolution changes.
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void CreateGUI() { }
|
||||||
|
|
||||||
//Starts a coroutine that will read the correct state of the component from the NetBuffer when correctionTimer reaches zero.
|
//Starts a coroutine that will read the correct state of the component from the NetBuffer when correctionTimer reaches zero.
|
||||||
protected void StartDelayedCorrection(ServerNetObject type, IReadMessage buffer, float sendingTime, bool waitForMidRoundSync = false)
|
protected void StartDelayedCorrection(ServerNetObject type, IReadMessage buffer, float sendingTime, bool waitForMidRoundSync = false)
|
||||||
{
|
{
|
||||||
@@ -530,5 +557,29 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
yield return CoroutineStatus.Success;
|
yield return CoroutineStatus.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Launches when the parent of the GuiFrame is changed.
|
||||||
|
/// </summary>
|
||||||
|
protected void OnGUIParentChanged(RectTransform newParent)
|
||||||
|
{
|
||||||
|
if (newParent == null)
|
||||||
|
{
|
||||||
|
// Make sure to unregister. It doesn't matter if we haven't ever registered to the event.
|
||||||
|
GameMain.Instance.ResolutionChanged -= OnResolutionChangedPrivate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnResolutionChanged() { }
|
||||||
|
|
||||||
|
private void OnResolutionChangedPrivate()
|
||||||
|
{
|
||||||
|
if (RecreateGUIOnResolutionChange)
|
||||||
|
{
|
||||||
|
ReloadGuiFrame();
|
||||||
|
CreateGUI();
|
||||||
|
}
|
||||||
|
OnResolutionChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,6 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private GUICustomComponent guiCustomComponent;
|
private GUICustomComponent guiCustomComponent;
|
||||||
|
|
||||||
private Point prevResolution;
|
|
||||||
|
|
||||||
public Sprite InventoryTopSprite
|
public Sprite InventoryTopSprite
|
||||||
{
|
{
|
||||||
get { return inventoryTopSprite; }
|
get { return inventoryTopSprite; }
|
||||||
@@ -115,16 +113,16 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
|
GuiFrame.RectTransform.ParentChanged += OnGUIParentChanged;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//if a GUIFrame has been defined, draw the inventory inside it
|
//if a GUIFrame has been defined, draw the inventory inside it
|
||||||
CreateGUI();
|
CreateGUI();
|
||||||
prevResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateGUI()
|
protected override void CreateGUI()
|
||||||
{
|
{
|
||||||
var content = new GUIFrame(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center) { AbsoluteOffset = GUIStyle.ItemFrameOffset },
|
var content = new GUIFrame(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center) { AbsoluteOffset = GUIStyle.ItemFrameOffset },
|
||||||
style: null)
|
style: null)
|
||||||
@@ -167,16 +165,6 @@ namespace Barotrauma.Items.Components
|
|||||||
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1)
|
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1)
|
||||||
{
|
{
|
||||||
if (hideItems || (item.body != null && !item.body.Enabled)) { return; }
|
if (hideItems || (item.body != null && !item.body.Enabled)) { return; }
|
||||||
|
|
||||||
if ((prevResolution.X > 0 && prevResolution.Y > 0) &&
|
|
||||||
(prevResolution.X != GameMain.GraphicsWidth || prevResolution.Y != GameMain.GraphicsHeight))
|
|
||||||
{
|
|
||||||
GuiFrame.ClearChildren();
|
|
||||||
CreateGUI();
|
|
||||||
|
|
||||||
prevResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawContainedItems(spriteBatch, itemDepth);
|
DrawContainedItems(spriteBatch, itemDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,7 +226,7 @@ namespace Barotrauma.Items.Components
|
|||||||
if (item.FlippedY) { origin.Y = containedItem.Sprite.SourceRect.Height - origin.Y; }
|
if (item.FlippedY) { origin.Y = containedItem.Sprite.SourceRect.Height - origin.Y; }
|
||||||
|
|
||||||
float containedSpriteDepth = ContainedSpriteDepth < 0.0f ? containedItem.Sprite.Depth : ContainedSpriteDepth;
|
float containedSpriteDepth = ContainedSpriteDepth < 0.0f ? containedItem.Sprite.Depth : ContainedSpriteDepth;
|
||||||
containedSpriteDepth = itemDepth + (containedSpriteDepth - item.SpriteDepth) / 10000.0f;
|
containedSpriteDepth = itemDepth + (containedSpriteDepth - (item.Sprite?.Depth ?? item.SpriteDepth)) / 10000.0f;
|
||||||
|
|
||||||
containedItem.Sprite.Draw(
|
containedItem.Sprite.Draw(
|
||||||
spriteBatch,
|
spriteBatch,
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private float[] charWidths;
|
private float[] charWidths;
|
||||||
|
|
||||||
[Serialize("0,0,0,0", true, description: "The amount of padding around the text in pixels (left,top,right,bottom). ")]
|
[Serialize("0,0,0,0", true, description: "The amount of padding around the text in pixels (left,top,right,bottom).")]
|
||||||
public Vector4 Padding
|
public Vector4 Padding
|
||||||
{
|
{
|
||||||
get { return TextBlock.Padding; }
|
get { return TextBlock.Padding; }
|
||||||
@@ -34,7 +34,7 @@ namespace Barotrauma.Items.Components
|
|||||||
get { return text; }
|
get { return text; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (value == text || item.Rect.Width < 5) return;
|
if (value == text || item.Rect.Width < 5) { return; }
|
||||||
|
|
||||||
if (TextBlock.Rect.Width != item.Rect.Width || textBlock.Rect.Height != item.Rect.Height)
|
if (TextBlock.Rect.Width != item.Rect.Width || textBlock.Rect.Height != item.Rect.Height)
|
||||||
{
|
{
|
||||||
@@ -64,7 +64,7 @@ namespace Barotrauma.Items.Components
|
|||||||
get { return textColor; }
|
get { return textColor; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (textBlock != null) textBlock.TextColor = value;
|
if (textBlock != null) { textBlock.TextColor = value; }
|
||||||
textColor = value;
|
textColor = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,7 +75,7 @@ namespace Barotrauma.Items.Components
|
|||||||
get { return textBlock == null ? 1.0f : textBlock.TextScale; }
|
get { return textBlock == null ? 1.0f : textBlock.TextScale; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (textBlock != null) textBlock.TextScale = MathHelper.Clamp(value, 0.1f, 10.0f);
|
if (textBlock != null) { textBlock.TextScale = MathHelper.Clamp(value, 0.1f, 10.0f); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ namespace Barotrauma.Items.Components
|
|||||||
if (textBlock == null)
|
if (textBlock == null)
|
||||||
{
|
{
|
||||||
textBlock = new GUITextBlock(new RectTransform(item.Rect.Size), "",
|
textBlock = new GUITextBlock(new RectTransform(item.Rect.Size), "",
|
||||||
textColor: textColor, font: GUI.UnscaledSmallFont, textAlignment: Alignment.Center, wrap: true, style: null)
|
textColor: textColor, font: GUI.UnscaledSmallFont, textAlignment: scrollable ? Alignment.CenterLeft : Alignment.Center, wrap: true, style: null)
|
||||||
{
|
{
|
||||||
TextDepth = item.SpriteDepth - 0.00001f,
|
TextDepth = item.SpriteDepth - 0.00001f,
|
||||||
RoundToNearestPixel = false,
|
RoundToNearestPixel = false,
|
||||||
|
|||||||
@@ -27,8 +27,9 @@ namespace Barotrauma.Items.Components
|
|||||||
if (backgroundSprite == null) { return; }
|
if (backgroundSprite == null) { return; }
|
||||||
|
|
||||||
backgroundSprite.DrawTiled(spriteBatch,
|
backgroundSprite.DrawTiled(spriteBatch,
|
||||||
new Vector2(item.DrawPosition.X - item.Rect.Width / 2, -(item.DrawPosition.Y + item.Rect.Height / 2)) - backgroundSprite.Origin,
|
new Vector2(item.DrawPosition.X - item.Rect.Width / 2 * item.Scale, -(item.DrawPosition.Y + item.Rect.Height / 2)) - backgroundSprite.Origin * item.Scale,
|
||||||
new Vector2(backgroundSprite.size.X, item.Rect.Height), color: item.Color,
|
new Vector2(backgroundSprite.size.X * item.Scale, item.Rect.Height), color: item.Color,
|
||||||
|
textureScale: Vector2.One * item.Scale,
|
||||||
depth: BackgroundSpriteDepth);
|
depth: BackgroundSpriteDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Barotrauma.Networking;
|
using Barotrauma.Networking;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
namespace Barotrauma.Items.Components
|
namespace Barotrauma.Items.Components
|
||||||
{
|
{
|
||||||
@@ -74,6 +75,21 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
public override void CreateEditingHUD(SerializableEntityEditor editor)
|
||||||
|
{
|
||||||
|
base.CreateEditingHUD(editor);
|
||||||
|
|
||||||
|
foreach (LimbPos limbPos in limbPositions)
|
||||||
|
{
|
||||||
|
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(limbPos);
|
||||||
|
|
||||||
|
PropertyDescriptor limbPosProperty = properties.Find("Position", false);
|
||||||
|
editor.CreateVector2Field(limbPos, new SerializableProperty(limbPosProperty), limbPos.Position, limbPos.LimbType.ToString(), "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
State = msg.ReadBoolean();
|
State = msg.ReadBoolean();
|
||||||
|
|||||||
+3
-10
@@ -23,17 +23,15 @@ namespace Barotrauma.Items.Components
|
|||||||
partial void InitProjSpecific(XElement element)
|
partial void InitProjSpecific(XElement element)
|
||||||
{
|
{
|
||||||
CreateGUI();
|
CreateGUI();
|
||||||
GameMain.Instance.OnResolutionChanged += RecreateGUI;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RecreateGUI()
|
protected override void OnResolutionChanged()
|
||||||
{
|
{
|
||||||
GuiFrame.ClearChildren();
|
base.OnResolutionChanged();
|
||||||
CreateGUI();
|
|
||||||
OnItemLoadedProjSpecific();
|
OnItemLoadedProjSpecific();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateGUI()
|
protected override void CreateGUI()
|
||||||
{
|
{
|
||||||
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.90f, 0.80f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter)
|
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.90f, 0.80f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter)
|
||||||
{
|
{
|
||||||
@@ -170,10 +168,5 @@ namespace Barotrauma.Items.Components
|
|||||||
SetActive(msg.ReadBoolean());
|
SetActive(msg.ReadBoolean());
|
||||||
progressTimer = msg.ReadSingle();
|
progressTimer = msg.ReadSingle();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void RemoveComponentSpecific()
|
|
||||||
{
|
|
||||||
GameMain.Instance.OnResolutionChanged -= RecreateGUI;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,17 +42,15 @@ namespace Barotrauma.Items.Components
|
|||||||
partial void InitProjSpecific()
|
partial void InitProjSpecific()
|
||||||
{
|
{
|
||||||
CreateGUI();
|
CreateGUI();
|
||||||
GameMain.Instance.OnResolutionChanged += RecreateGUI;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RecreateGUI()
|
protected override void OnResolutionChanged()
|
||||||
{
|
{
|
||||||
GuiFrame.ClearChildren();
|
base.OnResolutionChanged();
|
||||||
CreateGUI();
|
|
||||||
OnItemLoadedProjSpecific();
|
OnItemLoadedProjSpecific();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateGUI()
|
protected override void CreateGUI()
|
||||||
{
|
{
|
||||||
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter);
|
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter);
|
||||||
|
|
||||||
@@ -242,8 +240,8 @@ namespace Barotrauma.Items.Components
|
|||||||
var item1 = c1.GUIComponent.UserData as FabricationRecipe;
|
var item1 = c1.GUIComponent.UserData as FabricationRecipe;
|
||||||
var item2 = c2.GUIComponent.UserData as FabricationRecipe;
|
var item2 = c2.GUIComponent.UserData as FabricationRecipe;
|
||||||
|
|
||||||
bool hasSkills1 = DegreeOfSuccess(character, item1.RequiredSkills) >= 0.5f;
|
bool hasSkills1 = FabricationDegreeOfSuccess(character, item1.RequiredSkills) >= 0.5f;
|
||||||
bool hasSkills2 = DegreeOfSuccess(character, item2.RequiredSkills) >= 0.5f;
|
bool hasSkills2 = FabricationDegreeOfSuccess(character, item2.RequiredSkills) >= 0.5f;
|
||||||
|
|
||||||
if (hasSkills1 != hasSkills2)
|
if (hasSkills1 != hasSkills2)
|
||||||
{
|
{
|
||||||
@@ -267,7 +265,7 @@ namespace Barotrauma.Items.Components
|
|||||||
AutoScaleHorizontal = true,
|
AutoScaleHorizontal = true,
|
||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
var firstinSufficient = itemList.Content.Children.FirstOrDefault(c => c.UserData is FabricationRecipe fabricableItem && DegreeOfSuccess(character, fabricableItem.RequiredSkills) < 0.5f);
|
var firstinSufficient = itemList.Content.Children.FirstOrDefault(c => c.UserData is FabricationRecipe fabricableItem && FabricationDegreeOfSuccess(character, fabricableItem.RequiredSkills) < 0.5f);
|
||||||
if (firstinSufficient != null)
|
if (firstinSufficient != null)
|
||||||
{
|
{
|
||||||
insufficientSkillsText.RectTransform.RepositionChildInHierarchy(itemList.Content.RectTransform.GetChildIndex(firstinSufficient.RectTransform));
|
insufficientSkillsText.RectTransform.RepositionChildInHierarchy(itemList.Content.RectTransform.GetChildIndex(firstinSufficient.RectTransform));
|
||||||
@@ -476,7 +474,7 @@ namespace Barotrauma.Items.Components
|
|||||||
List<Skill> inadequateSkills = new List<Skill>();
|
List<Skill> inadequateSkills = new List<Skill>();
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
inadequateSkills = selectedItem.RequiredSkills.FindAll(skill => user.GetSkillLevel(skill.Identifier) < skill.Level);
|
inadequateSkills = selectedItem.RequiredSkills.FindAll(skill => user.GetSkillLevel(skill.Identifier) < Math.Round(skill.Level * SkillRequirementMultiplier));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedItem.RequiredSkills.Any())
|
if (selectedItem.RequiredSkills.Any())
|
||||||
@@ -489,13 +487,13 @@ namespace Barotrauma.Items.Components
|
|||||||
};
|
};
|
||||||
foreach (Skill skill in selectedItem.RequiredSkills)
|
foreach (Skill skill in selectedItem.RequiredSkills)
|
||||||
{
|
{
|
||||||
text += TextManager.Get("SkillName." + skill.Identifier) + " " + TextManager.Get("Lvl").ToLower() + " " + skill.Level;
|
text += TextManager.Get("SkillName." + skill.Identifier) + " " + TextManager.Get("Lvl").ToLower() + " " + Math.Round(skill.Level * SkillRequirementMultiplier);
|
||||||
if (skill != selectedItem.RequiredSkills.Last()) { text += "\n"; }
|
if (skill != selectedItem.RequiredSkills.Last()) { text += "\n"; }
|
||||||
}
|
}
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedReqFrame.RectTransform), text, font: GUI.SmallFont);
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedReqFrame.RectTransform), text, font: GUI.SmallFont);
|
||||||
}
|
}
|
||||||
|
|
||||||
float degreeOfSuccess = user == null ? 0.0f : DegreeOfSuccess(user, selectedItem.RequiredSkills);
|
float degreeOfSuccess = user == null ? 0.0f : FabricationDegreeOfSuccess(user, selectedItem.RequiredSkills);
|
||||||
if (degreeOfSuccess > 0.5f) { degreeOfSuccess = 1.0f; }
|
if (degreeOfSuccess > 0.5f) { degreeOfSuccess = 1.0f; }
|
||||||
|
|
||||||
float requiredTime = user == null ? selectedItem.RequiredTime : GetRequiredTime(selectedItem, user);
|
float requiredTime = user == null ? selectedItem.RequiredTime : GetRequiredTime(selectedItem, user);
|
||||||
@@ -621,10 +619,5 @@ namespace Barotrauma.Items.Components
|
|||||||
StartFabricating(fabricationRecipes[itemIndex], user);
|
StartFabricating(fabricationRecipes[itemIndex], user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void RemoveComponentSpecific()
|
|
||||||
{
|
|
||||||
GameMain.Instance.OnResolutionChanged -= RecreateGUI;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,17 @@ namespace Barotrauma.Items.Components
|
|||||||
partial void InitProjSpecific(XElement element)
|
partial void InitProjSpecific(XElement element)
|
||||||
{
|
{
|
||||||
noPowerTip = TextManager.Get("SteeringNoPowerTip");
|
noPowerTip = TextManager.Get("SteeringNoPowerTip");
|
||||||
|
CreateGUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnResolutionChanged()
|
||||||
|
{
|
||||||
|
base.OnResolutionChanged();
|
||||||
|
CreateHUD();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void CreateGUI()
|
||||||
|
{
|
||||||
GuiFrame.RectTransform.RelativeOffset = new Vector2(0.05f, 0.0f);
|
GuiFrame.RectTransform.RelativeOffset = new Vector2(0.05f, 0.0f);
|
||||||
GuiFrame.CanBeFocused = true;
|
GuiFrame.CanBeFocused = true;
|
||||||
new GUICustomComponent(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center) { AbsoluteOffset = GUIStyle.ItemFrameOffset },
|
new GUICustomComponent(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center) { AbsoluteOffset = GUIStyle.ItemFrameOffset },
|
||||||
@@ -53,7 +63,11 @@ namespace Barotrauma.Items.Components
|
|||||||
hullAirQualityText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), hullInfoContainer.RectTransform), "") { Wrap = true };
|
hullAirQualityText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), hullInfoContainer.RectTransform), "") { Wrap = true };
|
||||||
hullWaterText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), hullInfoContainer.RectTransform), "") { Wrap = true };
|
hullWaterText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), hullInfoContainer.RectTransform), "") { Wrap = true };
|
||||||
|
|
||||||
hullInfoFrame.Children.ForEach(c => { c.CanBeFocused = false; c.Children.ForEach(c2 => c2.CanBeFocused = false); });
|
hullInfoFrame.Children.ForEach(c =>
|
||||||
|
{
|
||||||
|
c.CanBeFocused = false;
|
||||||
|
c.Children.ForEach(c2 => c2.CanBeFocused = false);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void AddToGUIUpdateList()
|
public override void AddToGUIUpdateList()
|
||||||
@@ -72,7 +86,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
submarineContainer.ClearChildren();
|
submarineContainer.ClearChildren();
|
||||||
|
|
||||||
if (item.Submarine == null) return;
|
if (item.Submarine == null) { return; }
|
||||||
|
|
||||||
item.Submarine.CreateMiniMap(submarineContainer);
|
item.Submarine.CreateMiniMap(submarineContainer);
|
||||||
displayedSubs.Clear();
|
displayedSubs.Clear();
|
||||||
@@ -125,10 +139,8 @@ namespace Barotrauma.Items.Components
|
|||||||
GUI.Style.Orange * (float)Math.Abs(Math.Sin(Timing.TotalTime)), Color.Black * 0.8f, font: GUI.SubHeadingFont);
|
GUI.Style.Orange * (float)Math.Abs(Math.Sin(Timing.TotalTime)), Color.Black * 0.8f, font: GUI.SubHeadingFont);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!submarineContainer.Children.Any()) { return; }
|
if (!submarineContainer.Children.Any()) { return; }
|
||||||
|
foreach (GUIComponent child in submarineContainer.Children.FirstOrDefault()?.Children)
|
||||||
foreach (GUIComponent child in submarineContainer.Children.First().Children)
|
|
||||||
{
|
{
|
||||||
if (child.UserData is Hull hull)
|
if (child.UserData is Hull hull)
|
||||||
{
|
{
|
||||||
@@ -177,9 +189,19 @@ namespace Barotrauma.Items.Components
|
|||||||
HashSet<Submarine> subs = new HashSet<Submarine>();
|
HashSet<Submarine> subs = new HashSet<Submarine>();
|
||||||
foreach (Hull hull in Hull.hullList)
|
foreach (Hull hull in Hull.hullList)
|
||||||
{
|
{
|
||||||
if (hull.Submarine == null) continue;
|
if (hull.Submarine == null) { continue; }
|
||||||
var hullFrame = submarineContainer.Children.FirstOrDefault()?.FindChild(hull);
|
var hullFrame = submarineContainer.Children.FirstOrDefault()?.FindChild(hull);
|
||||||
if (hullFrame == null) continue;
|
if (hullFrame == null) { continue; }
|
||||||
|
|
||||||
|
hullFrame.Visible = true;
|
||||||
|
if (!submarineContainer.Rect.Contains(hullFrame.Rect))
|
||||||
|
{
|
||||||
|
if (hull.Submarine.Info.Type != SubmarineType.Player)
|
||||||
|
{
|
||||||
|
hullFrame.Visible = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
hullDatas.TryGetValue(hull, out HullData hullData);
|
hullDatas.TryGetValue(hull, out HullData hullData);
|
||||||
if (hullData == null)
|
if (hullData == null)
|
||||||
@@ -294,7 +316,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
foreach (Submarine sub in subs)
|
foreach (Submarine sub in subs)
|
||||||
{
|
{
|
||||||
if (sub.HullVertices == null) { continue; }
|
if (sub.HullVertices == null || sub.Info.IsOutpost) { continue; }
|
||||||
|
|
||||||
Rectangle worldBorders = sub.GetDockedBorders();
|
Rectangle worldBorders = sub.GetDockedBorders();
|
||||||
worldBorders.Location += sub.WorldPosition.ToPoint();
|
worldBorders.Location += sub.WorldPosition.ToPoint();
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
|
||||||
|
namespace Barotrauma.Items.Components
|
||||||
|
{
|
||||||
|
partial class OutpostTerminal : ItemComponent
|
||||||
|
{
|
||||||
|
private SubmarineSelection selectionUI;
|
||||||
|
|
||||||
|
public override bool Select(Character character)
|
||||||
|
{
|
||||||
|
if (GameMain.GameSession?.Campaign == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectionUI == null)
|
||||||
|
{
|
||||||
|
selectionUI = new SubmarineSelection(true, null, GUICanvas.Instance.ItemComponentHolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
GuiFrame = selectionUI.GuiFrame;
|
||||||
|
selectionUI.RefreshSubmarineDisplay(true);
|
||||||
|
IsActive = true;
|
||||||
|
return base.Select(character);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(float deltaTime, Camera cam)
|
||||||
|
{
|
||||||
|
if (Character.Controlled?.SelectedConstruction != item)
|
||||||
|
{
|
||||||
|
IsActive = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.Update(deltaTime, cam);
|
||||||
|
|
||||||
|
if (selectionUI != null)
|
||||||
|
{
|
||||||
|
selectionUI.Update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -157,16 +157,15 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
CreateGUI();
|
CreateGUI();
|
||||||
GameMain.Instance.OnResolutionChanged += RecreateGUI;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RecreateGUI()
|
protected override void OnResolutionChanged()
|
||||||
{
|
{
|
||||||
GuiFrame.ClearChildren();
|
base.OnResolutionChanged();
|
||||||
CreateGUI();
|
UpdateGUIElements();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateGUI()
|
protected override void CreateGUI()
|
||||||
{
|
{
|
||||||
bool isConnectedToSteering = item.GetComponent<Steering>() != null;
|
bool isConnectedToSteering = item.GetComponent<Steering>() != null;
|
||||||
Vector2 size = isConnectedToSteering ? controlBoxSize : new Vector2(controlBoxSize.X * 2.0f, controlBoxSize.Y);
|
Vector2 size = isConnectedToSteering ? controlBoxSize : new Vector2(controlBoxSize.X * 2.0f, controlBoxSize.Y);
|
||||||
@@ -667,23 +666,27 @@ namespace Barotrauma.Items.Components
|
|||||||
signalWarningText.Visible = false;
|
signalWarningText.Visible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameMain.GameSession == null) { return; }
|
if (GameMain.GameSession == null || Level.Loaded == null) { return; }
|
||||||
|
|
||||||
if (Level.Loaded == null) { return; }
|
if (Level.Loaded.StartLocation != null)
|
||||||
|
{
|
||||||
|
DrawMarker(spriteBatch,
|
||||||
|
Level.Loaded.StartLocation.Name,
|
||||||
|
"outpost",
|
||||||
|
Level.Loaded.StartLocation.Name,
|
||||||
|
Level.Loaded.StartPosition, transducerCenter,
|
||||||
|
displayScale, center, DisplayRadius);
|
||||||
|
}
|
||||||
|
|
||||||
DrawMarker(spriteBatch,
|
if (Level.Loaded.EndLocation != null && Level.Loaded.Type == LevelData.LevelType.LocationConnection)
|
||||||
GameMain.GameSession.StartLocation.Name,
|
{
|
||||||
"outpost",
|
DrawMarker(spriteBatch,
|
||||||
GameMain.GameSession.StartLocation.Name,
|
Level.Loaded.EndLocation.Name,
|
||||||
Level.Loaded.StartPosition, transducerCenter,
|
"outpost",
|
||||||
displayScale, center, DisplayRadius);
|
Level.Loaded.EndLocation.Name,
|
||||||
|
Level.Loaded.EndPosition, transducerCenter,
|
||||||
DrawMarker(spriteBatch,
|
displayScale, center, DisplayRadius);
|
||||||
GameMain.GameSession.EndLocation.Name,
|
}
|
||||||
"outpost",
|
|
||||||
GameMain.GameSession.EndLocation.Name,
|
|
||||||
Level.Loaded.EndPosition, transducerCenter,
|
|
||||||
displayScale, center, DisplayRadius);
|
|
||||||
|
|
||||||
foreach (AITarget aiTarget in AITarget.List)
|
foreach (AITarget aiTarget in AITarget.List)
|
||||||
{
|
{
|
||||||
@@ -1444,8 +1447,6 @@ namespace Barotrauma.Items.Components
|
|||||||
sprite.Remove();
|
sprite.Remove();
|
||||||
}
|
}
|
||||||
targetIcons.Clear();
|
targetIcons.Clear();
|
||||||
|
|
||||||
GameMain.Instance.OnResolutionChanged -= RecreateGUI;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private bool? swapDestinationOrder;
|
private bool? swapDestinationOrder;
|
||||||
|
|
||||||
|
private GUIMessageBox enterOutpostPrompt;
|
||||||
|
|
||||||
private bool levelStartSelected;
|
private bool levelStartSelected;
|
||||||
public bool LevelStartSelected
|
public bool LevelStartSelected
|
||||||
{
|
{
|
||||||
@@ -105,10 +107,9 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
CreateGUI();
|
CreateGUI();
|
||||||
GameMain.Instance.OnResolutionChanged += RecreateGUI;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateGUI()
|
protected override void CreateGUI()
|
||||||
{
|
{
|
||||||
controlContainer = new GUIFrame(new RectTransform(new Vector2(Sonar.controlBoxSize.X, 1 - Sonar.controlBoxSize.Y * 2), GuiFrame.RectTransform, Anchor.CenterLeft), "ItemUI");
|
controlContainer = new GUIFrame(new RectTransform(new Vector2(Sonar.controlBoxSize.X, 1 - Sonar.controlBoxSize.Y * 2), GuiFrame.RectTransform, Anchor.CenterLeft), "ItemUI");
|
||||||
var paddedControlContainer = new GUIFrame(new RectTransform(controlContainer.Rect.Size - GUIStyle.ItemFrameMargin, controlContainer.RectTransform, Anchor.Center)
|
var paddedControlContainer = new GUIFrame(new RectTransform(controlContainer.Rect.Size - GUIStyle.ItemFrameMargin, controlContainer.RectTransform, Anchor.Center)
|
||||||
@@ -220,11 +221,12 @@ namespace Barotrauma.Items.Components
|
|||||||
};
|
};
|
||||||
|
|
||||||
levelEndTickBox = new GUITickBox(new RectTransform(new Vector2(1, 0.333f), paddedAutoPilotControls.RectTransform, Anchor.BottomCenter),
|
levelEndTickBox = new GUITickBox(new RectTransform(new Vector2(1, 0.333f), paddedAutoPilotControls.RectTransform, Anchor.BottomCenter),
|
||||||
GameMain.GameSession?.EndLocation == null ? "" : ToolBox.LimitString(GameMain.GameSession.EndLocation.Name, textLimit),
|
(GameMain.GameSession?.EndLocation == null || Level.IsLoadedOutpost) ? "" : ToolBox.LimitString(GameMain.GameSession.EndLocation.Name, textLimit),
|
||||||
font: GUI.SmallFont, style: "GUIRadioButton")
|
font: GUI.SmallFont, style: "GUIRadioButton")
|
||||||
{
|
{
|
||||||
Enabled = autoPilot,
|
Enabled = autoPilot,
|
||||||
Selected = levelEndSelected,
|
Selected = levelEndSelected,
|
||||||
|
Visible = GameMain.GameSession?.EndLocation != null,
|
||||||
OnSelected = tickBox =>
|
OnSelected = tickBox =>
|
||||||
{
|
{
|
||||||
if (levelEndSelected != tickBox.Selected)
|
if (levelEndSelected != tickBox.Selected)
|
||||||
@@ -321,7 +323,7 @@ namespace Barotrauma.Items.Components
|
|||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
new GUITextBlock(new RectTransform(Vector2.One, left.RectTransform), leftText, font: GUI.SubHeadingFont, wrap: true, textAlignment: Alignment.CenterRight);
|
new GUITextBlock(new RectTransform(Vector2.One, left.RectTransform), leftText, font: GUI.SubHeadingFont, wrap: leftText.Contains(' '), textAlignment: Alignment.CenterRight);
|
||||||
new GUITextBlock(new RectTransform(Vector2.One, center.RectTransform), centerText, font: GUI.Font, textAlignment: Alignment.Center) { Padding = Vector4.Zero };
|
new GUITextBlock(new RectTransform(Vector2.One, center.RectTransform), centerText, font: GUI.Font, textAlignment: Alignment.Center) { Padding = Vector4.Zero };
|
||||||
var digitalFrame = new GUIFrame(new RectTransform(Vector2.One, right.RectTransform), style: "DigitalFrameDark");
|
var digitalFrame = new GUIFrame(new RectTransform(Vector2.One, right.RectTransform), style: "DigitalFrameDark");
|
||||||
new GUITextBlock(new RectTransform(Vector2.One * 0.85f, digitalFrame.RectTransform, Anchor.Center), "12345", GUI.Style.TextColorDark, GUI.DigitalFont, Alignment.CenterRight)
|
new GUITextBlock(new RectTransform(Vector2.One * 0.85f, digitalFrame.RectTransform, Anchor.Center), "12345", GUI.Style.TextColorDark, GUI.DigitalFont, Alignment.CenterRight)
|
||||||
@@ -347,18 +349,47 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
OnClicked = (btn, userdata) =>
|
OnClicked = (btn, userdata) =>
|
||||||
{
|
{
|
||||||
if (GameMain.Client == null)
|
|
||||||
|
if (GameMain.GameSession?.Campaign != null)
|
||||||
{
|
{
|
||||||
item.SendSignal(0, "1", "toggle_docking", sender: null);
|
if (Level.IsLoadedOutpost &&
|
||||||
}
|
DockingSources.Any(d => d.Docked && (d.DockingTarget?.Item.Submarine?.Info?.IsOutpost ?? false)))
|
||||||
else
|
{
|
||||||
{
|
GameMain.GameSession.Campaign.CampaignUI.SelectTab(CampaignMode.InteractionType.Map);
|
||||||
dockingNetworkMessagePending = true;
|
GameMain.GameSession.Campaign.ShowCampaignUI = true;
|
||||||
item.CreateClientEvent(this);
|
return false;
|
||||||
|
}
|
||||||
|
else if (!Level.IsLoadedOutpost && DockingModeEnabled && ActiveDockingSource != null &&
|
||||||
|
!ActiveDockingSource.Docked && (DockingTarget?.Item?.Submarine?.Info.IsOutpost ?? false))
|
||||||
|
{
|
||||||
|
enterOutpostPrompt = new GUIMessageBox("", TextManager.GetWithVariable("campaignenteroutpostprompt", "[locationname]", DockingTarget.Item.Submarine.Info.Name), new string[] { TextManager.Get("yes"), TextManager.Get("no") });
|
||||||
|
enterOutpostPrompt.Buttons[0].OnClicked += (btn, userdata) =>
|
||||||
|
{
|
||||||
|
SendDockingSignal();
|
||||||
|
enterOutpostPrompt.Close();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
enterOutpostPrompt.Buttons[1].OnClicked += enterOutpostPrompt.Close;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
SendDockingSignal();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
void SendDockingSignal()
|
||||||
|
{
|
||||||
|
if (GameMain.Client == null)
|
||||||
|
{
|
||||||
|
item.SendSignal(0, "1", "toggle_docking", sender: null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dockingNetworkMessagePending = true;
|
||||||
|
item.CreateClientEvent(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
dockingButton.Font = GUI.SubHeadingFont;
|
dockingButton.Font = GUI.SubHeadingFont;
|
||||||
dockingButton.TextBlock.RectTransform.MaxSize = new Point((int)(dockingButton.Rect.Width * 0.7f), int.MaxValue);
|
dockingButton.TextBlock.RectTransform.MaxSize = new Point((int)(dockingButton.Rect.Width * 0.7f), int.MaxValue);
|
||||||
dockingButton.TextBlock.AutoScaleHorizontal = true;
|
dockingButton.TextBlock.AutoScaleHorizontal = true;
|
||||||
@@ -413,10 +444,9 @@ namespace Barotrauma.Items.Components
|
|||||||
GameMain.GameSession?.EndLocation == null ? "End" : GameMain.GameSession.EndLocation.Name);
|
GameMain.GameSession?.EndLocation == null ? "End" : GameMain.GameSession.EndLocation.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RecreateGUI()
|
protected override void OnResolutionChanged()
|
||||||
{
|
{
|
||||||
GuiFrame.ClearChildren();
|
base.OnResolutionChanged();
|
||||||
CreateGUI();
|
|
||||||
UpdateGUIElements();
|
UpdateGUIElements();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -600,6 +630,10 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
dockingContainer.Visible = DockingModeEnabled;
|
dockingContainer.Visible = DockingModeEnabled;
|
||||||
statusContainer.Visible = !DockingModeEnabled;
|
statusContainer.Visible = !DockingModeEnabled;
|
||||||
|
if (!DockingModeEnabled)
|
||||||
|
{
|
||||||
|
enterOutpostPrompt?.Close();
|
||||||
|
}
|
||||||
|
|
||||||
if (DockingModeEnabled && ActiveDockingSource != null)
|
if (DockingModeEnabled && ActiveDockingSource != null)
|
||||||
{
|
{
|
||||||
@@ -613,6 +647,10 @@ namespace Barotrauma.Items.Components
|
|||||||
dockingButton.Pulsate(Vector2.One, Vector2.One * 1.2f, dockingButton.FlashTimer);
|
dockingButton.Pulsate(Vector2.One, Vector2.One * 1.2f, dockingButton.FlashTimer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enterOutpostPrompt?.Close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (DockingSources.Any(d => d.Docked))
|
else if (DockingSources.Any(d => d.Docked))
|
||||||
{
|
{
|
||||||
@@ -663,7 +701,8 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (Vector2.DistanceSquared(PlayerInput.MousePosition, steerArea.Rect.Center.ToVector2()) < steerRadius * steerRadius)
|
if (Vector2.DistanceSquared(PlayerInput.MousePosition, steerArea.Rect.Center.ToVector2()) < steerRadius * steerRadius)
|
||||||
{
|
{
|
||||||
if (PlayerInput.PrimaryMouseButtonHeld() && !CrewManager.IsCommandInterfaceOpen && !GameSession.IsTabMenuOpen)
|
if (PlayerInput.PrimaryMouseButtonHeld() && !CrewManager.IsCommandInterfaceOpen && !GameSession.IsTabMenuOpen &&
|
||||||
|
(!GameMain.GameSession?.Campaign?.ShowCampaignUI ?? true) && !GUIMessageBox.MessageBoxes.Any())
|
||||||
{
|
{
|
||||||
Vector2 inputPos = PlayerInput.MousePosition - steerArea.Rect.Center.ToVector2();
|
Vector2 inputPos = PlayerInput.MousePosition - steerArea.Rect.Center.ToVector2();
|
||||||
inputPos.Y = -inputPos.Y;
|
inputPos.Y = -inputPos.Y;
|
||||||
@@ -800,8 +839,7 @@ namespace Barotrauma.Items.Components
|
|||||||
maintainPosIndicator?.Remove();
|
maintainPosIndicator?.Remove();
|
||||||
maintainPosOriginIndicator?.Remove();
|
maintainPosOriginIndicator?.Remove();
|
||||||
steeringIndicator?.Remove();
|
steeringIndicator?.Remove();
|
||||||
|
enterOutpostPrompt?.Close();
|
||||||
GameMain.Instance.OnResolutionChanged -= RecreateGUI;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
||||||
|
|||||||
@@ -111,27 +111,28 @@ namespace Barotrauma.Items.Components
|
|||||||
if (item.FlippedX && item.Prefab.CanSpriteFlipX) { indicatorPos.X = -indicatorPos.X - indicatorSize.X * item.Scale; }
|
if (item.FlippedX && item.Prefab.CanSpriteFlipX) { indicatorPos.X = -indicatorPos.X - indicatorSize.X * item.Scale; }
|
||||||
if (item.FlippedY && item.Prefab.CanSpriteFlipY) { indicatorPos.Y = -indicatorPos.Y - indicatorSize.Y * item.Scale; }
|
if (item.FlippedY && item.Prefab.CanSpriteFlipY) { indicatorPos.Y = -indicatorPos.Y - indicatorSize.Y * item.Scale; }
|
||||||
|
|
||||||
if (charge > 0)
|
if (charge > 0 && capacity > 0)
|
||||||
{
|
{
|
||||||
Color indicatorColor = ToolBox.GradientLerp(charge / capacity, Color.Red, Color.Orange, Color.Green);
|
float chargeRatio = MathHelper.Clamp(charge / capacity, 0.0f, 1.0f);
|
||||||
|
Color indicatorColor = ToolBox.GradientLerp(chargeRatio, Color.Red, Color.Orange, Color.Green);
|
||||||
if (!isHorizontal)
|
if (!isHorizontal)
|
||||||
{
|
{
|
||||||
GUI.DrawRectangle(spriteBatch,
|
GUI.DrawRectangle(spriteBatch,
|
||||||
new Vector2(item.DrawPosition.X, -item.DrawPosition.Y + ((indicatorSize.Y * item.Scale) * (1.0f - charge / capacity))) + indicatorPos,
|
new Vector2(item.DrawPosition.X, -item.DrawPosition.Y + ((indicatorSize.Y * item.Scale) * (1.0f - chargeRatio))) + indicatorPos,
|
||||||
new Vector2(indicatorSize.X * item.Scale, (indicatorSize.Y * item.Scale) * (charge / capacity)), indicatorColor, true,
|
new Vector2(indicatorSize.X * item.Scale, (indicatorSize.Y * item.Scale) * chargeRatio), indicatorColor, true,
|
||||||
depth: item.SpriteDepth - 0.00001f);
|
depth: item.SpriteDepth - 0.00001f);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUI.DrawRectangle(spriteBatch,
|
GUI.DrawRectangle(spriteBatch,
|
||||||
new Vector2(item.DrawPosition.X, -item.DrawPosition.Y) + indicatorPos,
|
new Vector2(item.DrawPosition.X, -item.DrawPosition.Y) + indicatorPos,
|
||||||
new Vector2((indicatorSize.X * item.Scale) * (charge / capacity), indicatorSize.Y * item.Scale), indicatorColor, true,
|
new Vector2((indicatorSize.X * item.Scale) * chargeRatio, indicatorSize.Y * item.Scale), indicatorColor, true,
|
||||||
depth: item.SpriteDepth - 0.00001f);
|
depth: item.SpriteDepth - 0.00001f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GUI.DrawRectangle(spriteBatch,
|
GUI.DrawRectangle(spriteBatch,
|
||||||
new Vector2(item.DrawPosition.X, -item.DrawPosition.Y) + indicatorPos,
|
new Vector2(item.DrawPosition.X, -item.DrawPosition.Y) + indicatorPos,
|
||||||
indicatorSize * item.Scale, Color.Black, depth: item.SpriteDepth - 0.00001f);
|
indicatorSize * item.Scale, Color.Black, depth: item.SpriteDepth - 0.000015f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData)
|
public void ClientWrite(IWriteMessage msg, object[] extraData)
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ namespace Barotrauma.Items.Components
|
|||||||
var progressBar = user.UpdateHUDProgressBar(
|
var progressBar = user.UpdateHUDProgressBar(
|
||||||
targetStructure.ID * 1000 + sectionIndex, //unique "identifier" for each wall section
|
targetStructure.ID * 1000 + sectionIndex, //unique "identifier" for each wall section
|
||||||
progressBarPos,
|
progressBarPos,
|
||||||
1.0f - targetStructure.SectionDamage(sectionIndex) / targetStructure.Health,
|
MathUtils.InverseLerp(targetStructure.Prefab.MinHealth, targetStructure.Health, targetStructure.Health - targetStructure.SectionDamage(sectionIndex)),
|
||||||
GUI.Style.Red, GUI.Style.Green);
|
GUI.Style.Red, GUI.Style.Green);
|
||||||
|
|
||||||
if (progressBar != null) progressBar.Size = new Vector2(60.0f, 20.0f);
|
if (progressBar != null) progressBar.Size = new Vector2(60.0f, 20.0f);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Barotrauma.Networking;
|
using System;
|
||||||
|
using Barotrauma.Networking;
|
||||||
using Barotrauma.Particles;
|
using Barotrauma.Particles;
|
||||||
using Barotrauma.Sounds;
|
using Barotrauma.Sounds;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
@@ -49,6 +50,42 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
partial void InitProjSpecific(XElement element)
|
partial void InitProjSpecific(XElement element)
|
||||||
|
{
|
||||||
|
CreateGUI();
|
||||||
|
foreach (XElement subElement in element.Elements())
|
||||||
|
{
|
||||||
|
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||||
|
{
|
||||||
|
case "emitter":
|
||||||
|
case "particleemitter":
|
||||||
|
particleEmitters.Add(new ParticleEmitter(subElement));
|
||||||
|
float minCondition = subElement.GetAttributeFloat("mincondition", 0.0f);
|
||||||
|
float maxCondition = subElement.GetAttributeFloat("maxcondition", 100.0f);
|
||||||
|
|
||||||
|
if (maxCondition < minCondition)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("Invalid damage particle configuration in the Repairable component of " + item.Name + ". MaxCondition needs to be larger than MinCondition.");
|
||||||
|
float temp = maxCondition;
|
||||||
|
maxCondition = minCondition;
|
||||||
|
minCondition = temp;
|
||||||
|
}
|
||||||
|
particleEmitterConditionRanges.Add(new Vector2(minCondition, maxCondition));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RecreateGUI()
|
||||||
|
{
|
||||||
|
if (GuiFrame != null)
|
||||||
|
{
|
||||||
|
GuiFrame.ClearChildren();
|
||||||
|
CreateGUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateGUI()
|
||||||
{
|
{
|
||||||
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 0.75f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter)
|
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 0.75f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter)
|
||||||
{
|
{
|
||||||
@@ -68,7 +105,7 @@ namespace Barotrauma.Items.Components
|
|||||||
for (int i = 0; i < requiredSkills.Count; i++)
|
for (int i = 0; i < requiredSkills.Count; i++)
|
||||||
{
|
{
|
||||||
var skillText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform),
|
var skillText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform),
|
||||||
" - " + TextManager.AddPunctuation(':', TextManager.Get("SkillName." + requiredSkills[i].Identifier), ((int) requiredSkills[i].Level).ToString()),
|
" - " + TextManager.AddPunctuation(':', TextManager.Get("SkillName." + requiredSkills[i].Identifier), ((int) Math.Round(requiredSkills[i].Level * SkillRequirementMultiplier)).ToString()),
|
||||||
font: GUI.SmallFont)
|
font: GUI.SmallFont)
|
||||||
{
|
{
|
||||||
UserData = requiredSkills[i]
|
UserData = requiredSkills[i]
|
||||||
@@ -111,43 +148,27 @@ namespace Barotrauma.Items.Components
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (XElement subElement in element.Elements())
|
|
||||||
{
|
|
||||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
|
||||||
{
|
|
||||||
case "emitter":
|
|
||||||
case "particleemitter":
|
|
||||||
particleEmitters.Add(new ParticleEmitter(subElement));
|
|
||||||
float minCondition = subElement.GetAttributeFloat("mincondition", 0.0f);
|
|
||||||
float maxCondition = subElement.GetAttributeFloat("maxcondition", 100.0f);
|
|
||||||
|
|
||||||
if (maxCondition < minCondition)
|
|
||||||
{
|
|
||||||
DebugConsole.ThrowError("Invalid damage particle configuration in the Repairable component of " + item.Name + ". MaxCondition needs to be larger than MinCondition.");
|
|
||||||
float temp = maxCondition;
|
|
||||||
maxCondition = minCondition;
|
|
||||||
minCondition = temp;
|
|
||||||
}
|
|
||||||
particleEmitterConditionRanges.Add(new Vector2(minCondition, maxCondition));
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void UpdateProjSpecific(float deltaTime)
|
partial void UpdateProjSpecific(float deltaTime)
|
||||||
{
|
{
|
||||||
if (Character.Controlled == null || (Character.Controlled.CharacterHealth.GetAffliction("psychosis")?.Strength ?? 0.0f) <= 0.0f)
|
if (FakeBrokenTimer > 0.0f)
|
||||||
{
|
{
|
||||||
FakeBrokenTimer = 0.0f;
|
item.FakeBroken = true;
|
||||||
|
if (Character.Controlled == null || (Character.Controlled.CharacterHealth.GetAffliction("psychosis")?.Strength ?? 0.0f) <= 0.0f)
|
||||||
|
{
|
||||||
|
FakeBrokenTimer = 0.0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FakeBrokenTimer -= deltaTime;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FakeBrokenTimer -= deltaTime;
|
item.FakeBroken = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
item.FakeBroken = FakeBrokenTimer > 0.0f;
|
|
||||||
|
|
||||||
if (!GameMain.IsMultiplayer)
|
if (!GameMain.IsMultiplayer)
|
||||||
{
|
{
|
||||||
@@ -211,7 +232,7 @@ namespace Barotrauma.Items.Components
|
|||||||
if (!(c.UserData is Skill skill)) continue;
|
if (!(c.UserData is Skill skill)) continue;
|
||||||
|
|
||||||
GUITextBlock textBlock = (GUITextBlock)c;
|
GUITextBlock textBlock = (GUITextBlock)c;
|
||||||
if (character.GetSkillLevel(skill.Identifier) < skill.Level)
|
if (character.GetSkillLevel(skill.Identifier) < (skill.Level * SkillRequirementMultiplier))
|
||||||
{
|
{
|
||||||
textBlock.TextColor = GUI.Style.Red;
|
textBlock.TextColor = GUI.Style.Red;
|
||||||
}
|
}
|
||||||
@@ -247,6 +268,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
protected override void RemoveComponentSpecific()
|
protected override void RemoveComponentSpecific()
|
||||||
{
|
{
|
||||||
|
base.RemoveComponentSpecific();
|
||||||
repairSoundChannel?.FadeOutAndDispose();
|
repairSoundChannel?.FadeOutAndDispose();
|
||||||
repairSoundChannel = null;
|
repairSoundChannel = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -289,7 +289,7 @@ namespace Barotrauma.Items.Components
|
|||||||
flashColor * (float)Math.Sin(FlashTimer % flashCycleDuration / flashCycleDuration * MathHelper.Pi * 0.8f), scale: connectorSpriteScale);
|
flashColor * (float)Math.Sin(FlashTimer % flashCycleDuration / flashCycleDuration * MathHelper.Pi * 0.8f), scale: connectorSpriteScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Wires.Any(w => w != null && w != DraggingConnected))
|
if (Wires.Any(w => w != null && w != DraggingConnected && !w.Hidden))
|
||||||
{
|
{
|
||||||
int screwIndex = (int)Math.Floor(position.Y / 30.0f) % screwSprites.Count;
|
int screwIndex = (int)Math.Floor(position.Y / 30.0f) % screwSprites.Count;
|
||||||
screwSprites[screwIndex].Draw(spriteBatch, position, scale: connectorSpriteScale);
|
screwSprites[screwIndex].Draw(spriteBatch, position, scale: connectorSpriteScale);
|
||||||
|
|||||||
+1
-14
@@ -18,17 +18,9 @@ namespace Barotrauma.Items.Components
|
|||||||
partial void InitProjSpecific(XElement element)
|
partial void InitProjSpecific(XElement element)
|
||||||
{
|
{
|
||||||
CreateGUI();
|
CreateGUI();
|
||||||
GameMain.Instance.OnResolutionChanged += RecreateGUI;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RecreateGUI()
|
protected override void CreateGUI()
|
||||||
{
|
|
||||||
GuiFrame.ClearChildren();
|
|
||||||
CreateGUI();
|
|
||||||
UpdateLabelsProjSpecific();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreateGUI()
|
|
||||||
{
|
{
|
||||||
uiElements.Clear();
|
uiElements.Clear();
|
||||||
var visibleElements = customInterfaceElementList.Where(ciElement => !string.IsNullOrEmpty(ciElement.Label));
|
var visibleElements = customInterfaceElementList.Where(ciElement => !string.IsNullOrEmpty(ciElement.Label));
|
||||||
@@ -309,10 +301,5 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void RemoveComponentSpecific()
|
|
||||||
{
|
|
||||||
GameMain.Instance.OnResolutionChanged -= RecreateGUI;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
if (IsActive && item.ParentInventory?.Owner is Character user && user == Character.Controlled)// && Vector2.Distance(newNodePos, nodes[nodes.Count - 1]) > nodeDistance)
|
if (IsActive && item.ParentInventory?.Owner is Character user && user == Character.Controlled)// && Vector2.Distance(newNodePos, nodes[nodes.Count - 1]) > nodeDistance)
|
||||||
{
|
{
|
||||||
if (user.CanInteract)
|
if (user.CanInteract && currLength < MaxLength)
|
||||||
{
|
{
|
||||||
Vector2 gridPos = Character.Controlled.Position;
|
Vector2 gridPos = Character.Controlled.Position;
|
||||||
Vector2 roundedGridPos = new Vector2(
|
Vector2 roundedGridPos = new Vector2(
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ namespace Barotrauma.Items.Components
|
|||||||
Entity targetEntity = Entity.FindEntityByID(dockingTargetID);
|
Entity targetEntity = Entity.FindEntityByID(dockingTargetID);
|
||||||
if (targetEntity == null || !(targetEntity is Item))
|
if (targetEntity == null || !(targetEntity is Item))
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Invalid docking port network event (can't dock to " + targetEntity?.ToString() ?? "null" + ")");
|
DebugConsole.ThrowError("Invalid docking port network event (can't dock to " + (targetEntity?.ToString() ?? "null") + ")");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -260,7 +260,11 @@ namespace Barotrauma
|
|||||||
item.Name :
|
item.Name :
|
||||||
item.Name + '\n' + description;
|
item.Name + '\n' + description;
|
||||||
}
|
}
|
||||||
|
if (item.SpawnedInOutpost)
|
||||||
|
{
|
||||||
|
string colorStr = XMLExtensions.ColorToString(GUI.Style.Red);
|
||||||
|
toolTip = $"‖color:{colorStr}‖{toolTip}‖color:end‖";
|
||||||
|
}
|
||||||
return toolTip;
|
return toolTip;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1127,6 +1131,8 @@ namespace Barotrauma
|
|||||||
public static void DrawFront(SpriteBatch spriteBatch)
|
public static void DrawFront(SpriteBatch spriteBatch)
|
||||||
{
|
{
|
||||||
if (GUI.PauseMenuOpen || GUI.SettingsMenuOpen) { return; }
|
if (GUI.PauseMenuOpen || GUI.SettingsMenuOpen) { return; }
|
||||||
|
if (GameMain.GameSession?.Campaign != null &&
|
||||||
|
(GameMain.GameSession.Campaign.ShowCampaignUI || GameMain.GameSession.Campaign.ForceMapUI)) { return; }
|
||||||
|
|
||||||
subInventorySlotsToDraw.Clear();
|
subInventorySlotsToDraw.Clear();
|
||||||
subInventorySlotsToDraw.AddRange(highlightedSubInventorySlots);
|
subInventorySlotsToDraw.AddRange(highlightedSubInventorySlots);
|
||||||
@@ -1377,6 +1383,17 @@ namespace Barotrauma
|
|||||||
sprite.Draw(spriteBatch, itemPos + Vector2.One * 2, Color.Black * 0.6f, rotate: rotation, scale: scale);
|
sprite.Draw(spriteBatch, itemPos + Vector2.One * 2, Color.Black * 0.6f, rotate: rotation, scale: scale);
|
||||||
}
|
}
|
||||||
sprite.Draw(spriteBatch, itemPos, spriteColor, rotation, scale);
|
sprite.Draw(spriteBatch, itemPos, spriteColor, rotation, scale);
|
||||||
|
|
||||||
|
if (item.SpawnedInOutpost && CharacterInventory.LimbSlotIcons.ContainsKey(InvSlotType.LeftHand))
|
||||||
|
{
|
||||||
|
var stealIcon = CharacterInventory.LimbSlotIcons[InvSlotType.LeftHand];
|
||||||
|
Vector2 iconSize = new Vector2(25 * GUI.Scale);
|
||||||
|
stealIcon.Draw(
|
||||||
|
spriteBatch,
|
||||||
|
new Vector2(rect.X + iconSize.X * 0.2f, rect.Bottom - iconSize.Y * 1.2f),
|
||||||
|
color: GUI.Style.Red,
|
||||||
|
scale: iconSize.X / stealIcon.size.X);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inventory != null &&
|
if (inventory != null &&
|
||||||
|
|||||||
@@ -246,7 +246,7 @@ namespace Barotrauma
|
|||||||
float fadeInBrokenSpriteAlpha = 0.0f;
|
float fadeInBrokenSpriteAlpha = 0.0f;
|
||||||
float displayCondition = FakeBroken ? 0.0f : condition;
|
float displayCondition = FakeBroken ? 0.0f : condition;
|
||||||
Vector2 drawOffset = Vector2.Zero;
|
Vector2 drawOffset = Vector2.Zero;
|
||||||
if (displayCondition < Prefab.Health)
|
if (displayCondition < MaxCondition)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < Prefab.BrokenSprites.Count; i++)
|
for (int i = 0; i < Prefab.BrokenSprites.Count; i++)
|
||||||
{
|
{
|
||||||
@@ -300,21 +300,22 @@ namespace Barotrauma
|
|||||||
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState) * Scale;
|
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState) * Scale;
|
||||||
decorativeSprite.Sprite.DrawTiled(spriteBatch,
|
decorativeSprite.Sprite.DrawTiled(spriteBatch,
|
||||||
new Vector2(DrawPosition.X + offset.X - rect.Width / 2, -(DrawPosition.Y + offset.Y + rect.Height / 2)),
|
new Vector2(DrawPosition.X + offset.X - rect.Width / 2, -(DrawPosition.Y + offset.Y + rect.Height / 2)),
|
||||||
new Vector2(rect.Width, rect.Height), color: color,
|
size, color: color,
|
||||||
|
textureScale: Vector2.One * Scale,
|
||||||
depth: Math.Min(depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth), 0.999f));
|
depth: Math.Min(depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth), 0.999f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
activeSprite.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y) + drawOffset, color, SpriteRotation, Scale, activeSprite.effects, depth);
|
activeSprite.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y) + drawOffset, color, SpriteRotation + rotation, Scale, activeSprite.effects, depth);
|
||||||
fadeInBrokenSprite?.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y) + fadeInBrokenSprite.Offset.ToVector2() * Scale, color * fadeInBrokenSpriteAlpha, SpriteRotation, Scale, activeSprite.effects, depth - 0.000001f);
|
fadeInBrokenSprite?.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y) + fadeInBrokenSprite.Offset.ToVector2() * Scale, color * fadeInBrokenSpriteAlpha, SpriteRotation + rotation, Scale, activeSprite.effects, depth - 0.000001f);
|
||||||
foreach (var decorativeSprite in Prefab.DecorativeSprites)
|
foreach (var decorativeSprite in Prefab.DecorativeSprites)
|
||||||
{
|
{
|
||||||
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
||||||
float rotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState);
|
float rot = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState);
|
||||||
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState) * Scale;
|
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState) * Scale;
|
||||||
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + offset.X, -(DrawPosition.Y + offset.Y)), color,
|
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + offset.X, -(DrawPosition.Y + offset.Y)), color,
|
||||||
SpriteRotation + rotation, decorativeSprite.Scale * Scale, activeSprite.effects,
|
SpriteRotation + rotation + rot, decorativeSprite.Scale * Scale, activeSprite.effects,
|
||||||
depth: Math.Min(depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth), 0.999f));
|
depth: Math.Min(depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth), 0.999f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -328,7 +329,7 @@ namespace Barotrauma
|
|||||||
if (holdable.Picker.SelectedItems[0] == this)
|
if (holdable.Picker.SelectedItems[0] == this)
|
||||||
{
|
{
|
||||||
Limb holdLimb = holdable.Picker.AnimController.GetLimb(LimbType.RightHand);
|
Limb holdLimb = holdable.Picker.AnimController.GetLimb(LimbType.RightHand);
|
||||||
if (holdLimb != null)
|
if (holdLimb?.ActiveSprite != null)
|
||||||
{
|
{
|
||||||
depth = holdLimb.ActiveSprite.Depth + holdable.Picker.AnimController.GetDepthOffset() + depthStep * 2;
|
depth = holdLimb.ActiveSprite.Depth + holdable.Picker.AnimController.GetDepthOffset() + depthStep * 2;
|
||||||
foreach (WearableSprite wearableSprite in holdLimb.WearingItems)
|
foreach (WearableSprite wearableSprite in holdLimb.WearingItems)
|
||||||
@@ -340,7 +341,7 @@ namespace Barotrauma
|
|||||||
else if (holdable.Picker.SelectedItems[1] == this)
|
else if (holdable.Picker.SelectedItems[1] == this)
|
||||||
{
|
{
|
||||||
Limb holdLimb = holdable.Picker.AnimController.GetLimb(LimbType.LeftHand);
|
Limb holdLimb = holdable.Picker.AnimController.GetLimb(LimbType.LeftHand);
|
||||||
if (holdLimb != null)
|
if (holdLimb?.ActiveSprite != null)
|
||||||
{
|
{
|
||||||
depth = holdLimb.ActiveSprite.Depth + holdable.Picker.AnimController.GetDepthOffset() - depthStep * 2;
|
depth = holdLimb.ActiveSprite.Depth + holdable.Picker.AnimController.GetDepthOffset() - depthStep * 2;
|
||||||
foreach (WearableSprite wearableSprite in holdLimb.WearingItems)
|
foreach (WearableSprite wearableSprite in holdLimb.WearingItems)
|
||||||
@@ -369,6 +370,23 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var upgrade in Upgrades)
|
||||||
|
{
|
||||||
|
var upgradeSprites = GetUpgradeSprites(upgrade);
|
||||||
|
|
||||||
|
foreach (var decorativeSprite in upgradeSprites)
|
||||||
|
{
|
||||||
|
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
||||||
|
float rotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState);
|
||||||
|
var (xOff, yOff) = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState) * Scale;
|
||||||
|
|
||||||
|
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + xOff, -(DrawPosition.Y + yOff)), color,
|
||||||
|
rotation, decorativeSprite.Scale * Scale, activeSprite.effects,
|
||||||
|
depth: depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
activeSprite.effects = oldEffects;
|
activeSprite.effects = oldEffects;
|
||||||
if (fadeInBrokenSprite != null && fadeInBrokenSprite.Sprite != activeSprite)
|
if (fadeInBrokenSprite != null && fadeInBrokenSprite.Sprite != activeSprite)
|
||||||
{
|
{
|
||||||
@@ -437,6 +455,21 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DrawDecorativeSprite(SpriteBatch spriteBatch, DecorativeSprite decorativeSprite, Color color, float depth)
|
||||||
|
{
|
||||||
|
if (!spriteAnimState[decorativeSprite].IsActive) { return; }
|
||||||
|
float rotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState);
|
||||||
|
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState) * Scale;
|
||||||
|
|
||||||
|
var ca = (float)Math.Cos(-body.Rotation);
|
||||||
|
var sa = (float)Math.Sin(-body.Rotation);
|
||||||
|
Vector2 transformedOffset = new Vector2(ca * offset.X + sa * offset.Y, -sa * offset.X + ca * offset.Y);
|
||||||
|
|
||||||
|
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + transformedOffset.X, -(DrawPosition.Y + transformedOffset.Y)), color,
|
||||||
|
-body.Rotation + rotation, decorativeSprite.Scale * Scale, activeSprite.effects,
|
||||||
|
depth: depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth));
|
||||||
|
}
|
||||||
|
|
||||||
partial void OnCollisionProjSpecific(float impact)
|
partial void OnCollisionProjSpecific(float impact)
|
||||||
{
|
{
|
||||||
if (impact > 1.0f &&
|
if (impact > 1.0f &&
|
||||||
@@ -451,6 +484,22 @@ namespace Barotrauma
|
|||||||
public void UpdateSpriteStates(float deltaTime)
|
public void UpdateSpriteStates(float deltaTime)
|
||||||
{
|
{
|
||||||
DecorativeSprite.UpdateSpriteStates(Prefab.DecorativeSpriteGroups, spriteAnimState, ID, deltaTime, ConditionalMatches);
|
DecorativeSprite.UpdateSpriteStates(Prefab.DecorativeSpriteGroups, spriteAnimState, ID, deltaTime, ConditionalMatches);
|
||||||
|
|
||||||
|
foreach (var upgrade in Upgrades)
|
||||||
|
{
|
||||||
|
var upgradeSprites = GetUpgradeSprites(upgrade);
|
||||||
|
|
||||||
|
foreach (var decorativeSprite in upgradeSprites)
|
||||||
|
{
|
||||||
|
var spriteState = spriteAnimState[decorativeSprite];
|
||||||
|
spriteState.IsActive = true;
|
||||||
|
foreach (var _ in decorativeSprite.IsActiveConditionals.Where(conditional => !ConditionalMatches(conditional)))
|
||||||
|
{
|
||||||
|
spriteState.IsActive = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void UpdateEditing(Camera cam)
|
public override void UpdateEditing(Camera cam)
|
||||||
@@ -541,12 +590,14 @@ namespace Barotrauma
|
|||||||
linkText.TextColor = GUI.Style.Orange;
|
linkText.TextColor = GUI.Style.Orange;
|
||||||
itemsText.TextColor = GUI.Style.Orange;
|
itemsText.TextColor = GUI.Style.Orange;
|
||||||
}
|
}
|
||||||
|
|
||||||
var buttonContainer = new GUILayoutGroup(new RectTransform(new Point(listBox.Content.Rect.Width, heightScaled)), isHorizontal: true)
|
var buttonContainer = new GUILayoutGroup(new RectTransform(new Point(listBox.Content.Rect.Width, heightScaled)), isHorizontal: true)
|
||||||
{
|
{
|
||||||
Stretch = true,
|
Stretch = true,
|
||||||
RelativeSpacing = 0.02f,
|
RelativeSpacing = 0.02f,
|
||||||
CanBeFocused = true
|
CanBeFocused = true
|
||||||
};
|
};
|
||||||
|
|
||||||
new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityX"), style: "GUIButtonSmall")
|
new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityX"), style: "GUIButtonSmall")
|
||||||
{
|
{
|
||||||
ToolTip = TextManager.Get("MirrorEntityXToolTip"),
|
ToolTip = TextManager.Get("MirrorEntityXToolTip"),
|
||||||
@@ -588,6 +639,22 @@ namespace Barotrauma
|
|||||||
buttonContainer.RectTransform.IsFixedSize = true;
|
buttonContainer.RectTransform.IsFixedSize = true;
|
||||||
itemEditor.AddCustomContent(buttonContainer, itemEditor.ContentCount);
|
itemEditor.AddCustomContent(buttonContainer, itemEditor.ContentCount);
|
||||||
GUITextBlock.AutoScaleAndNormalize(buttonContainer.Children.Select(b => ((GUIButton)b).TextBlock));
|
GUITextBlock.AutoScaleAndNormalize(buttonContainer.Children.Select(b => ((GUIButton)b).TextBlock));
|
||||||
|
|
||||||
|
if (Submarine.MainSub?.Info?.Type == SubmarineType.OutpostModule)
|
||||||
|
{
|
||||||
|
GUITickBox tickBox = new GUITickBox(new RectTransform(new Point(listBox.Content.Rect.Width, 10)), TextManager.Get("sp.structure.removeiflinkedoutpostdoorinuse.name"))
|
||||||
|
{
|
||||||
|
Font = GUI.SmallFont,
|
||||||
|
Selected = RemoveIfLinkedOutpostDoorInUse,
|
||||||
|
ToolTip = TextManager.Get("sp.structure.removeiflinkedoutpostdoorinuse.description"),
|
||||||
|
OnSelected = (tickBox) =>
|
||||||
|
{
|
||||||
|
RemoveIfLinkedOutpostDoorInUse = tickBox.Selected;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
itemEditor.AddCustomContent(tickBox, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (ItemComponent ic in components)
|
foreach (ItemComponent ic in components)
|
||||||
@@ -667,6 +734,39 @@ namespace Barotrauma
|
|||||||
return editingHUD;
|
return editingHUD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<DecorativeSprite> GetUpgradeSprites(Upgrade upgrade)
|
||||||
|
{
|
||||||
|
var upgradeSprites = upgrade.Prefab.DecorativeSprites;
|
||||||
|
|
||||||
|
if (Prefab.UpgradeOverrideSprites.ContainsKey(upgrade.Prefab.Identifier))
|
||||||
|
{
|
||||||
|
upgradeSprites = Prefab.UpgradeOverrideSprites[upgrade.Prefab.Identifier];
|
||||||
|
}
|
||||||
|
|
||||||
|
return upgradeSprites;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool AddUpgrade(Upgrade upgrade, bool createNetworkEvent = false)
|
||||||
|
{
|
||||||
|
if (upgrade.Prefab.IsWallUpgrade) { return false; }
|
||||||
|
bool result = base.AddUpgrade(upgrade, createNetworkEvent);
|
||||||
|
if (result && !upgrade.Disposed)
|
||||||
|
{
|
||||||
|
List<DecorativeSprite> upgradeSprites = GetUpgradeSprites(upgrade);
|
||||||
|
|
||||||
|
if (upgradeSprites.Any())
|
||||||
|
{
|
||||||
|
foreach (DecorativeSprite decorativeSprite in upgradeSprites)
|
||||||
|
{
|
||||||
|
decorativeSprite.Sprite.EnsureLazyLoaded();
|
||||||
|
spriteAnimState.Add(decorativeSprite, new DecorativeSprite.State());
|
||||||
|
}
|
||||||
|
UpdateSpriteStates(0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private void CreateTagPicker(GUITextBox textBox, IEnumerable<string> availableTags)
|
private void CreateTagPicker(GUITextBox textBox, IEnumerable<string> availableTags)
|
||||||
{
|
{
|
||||||
var msgBox = new GUIMessageBox("", "", new string[] { TextManager.Get("Cancel") }, new Vector2(0.2f, 0.5f), new Point(300, 400));
|
var msgBox = new GUIMessageBox("", "", new string[] { TextManager.Get("Cancel") }, new Vector2(0.2f, 0.5f), new Point(300, 400));
|
||||||
@@ -756,6 +856,10 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private readonly List<Rectangle> debugInitialHudPositions = new List<Rectangle>();
|
private readonly List<Rectangle> debugInitialHudPositions = new List<Rectangle>();
|
||||||
|
|
||||||
|
private readonly List<ItemComponent> prevActiveHUDs = new List<ItemComponent>();
|
||||||
|
private readonly List<ItemComponent> activeComponents = new List<ItemComponent>();
|
||||||
|
private readonly List<ItemComponent> maxPriorityHUDs = new List<ItemComponent>();
|
||||||
|
|
||||||
public void UpdateHUD(Camera cam, Character character, float deltaTime)
|
public void UpdateHUD(Camera cam, Character character, float deltaTime)
|
||||||
{
|
{
|
||||||
bool editingHUDCreated = false;
|
bool editingHUDCreated = false;
|
||||||
@@ -774,8 +878,11 @@ namespace Barotrauma
|
|||||||
editingHUDRefreshTimer -= deltaTime;
|
editingHUDRefreshTimer -= deltaTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ItemComponent> prevActiveHUDs = new List<ItemComponent>(activeHUDs);
|
prevActiveHUDs.Clear();
|
||||||
List<ItemComponent> activeComponents = new List<ItemComponent>(components);
|
prevActiveHUDs.AddRange(activeHUDs);
|
||||||
|
activeComponents.Clear();
|
||||||
|
activeComponents.AddRange(components);
|
||||||
|
|
||||||
foreach (MapEntity entity in linkedTo)
|
foreach (MapEntity entity in linkedTo)
|
||||||
{
|
{
|
||||||
if (prefab.IsLinkAllowed(entity.prefab) && entity is Item i)
|
if (prefab.IsLinkAllowed(entity.prefab) && entity is Item i)
|
||||||
@@ -788,12 +895,11 @@ namespace Barotrauma
|
|||||||
activeHUDs.Clear();
|
activeHUDs.Clear();
|
||||||
//the HUD of the component with the highest priority will be drawn
|
//the HUD of the component with the highest priority will be drawn
|
||||||
//if all components have a priority of 0, all of them are drawn
|
//if all components have a priority of 0, all of them are drawn
|
||||||
List<ItemComponent> maxPriorityHUDs = new List<ItemComponent>();
|
maxPriorityHUDs.Clear();
|
||||||
|
bool DrawHud(ItemComponent ic) => ic.ShouldDrawHUD(character) && (ic.CanBeSelected && ic.HasRequiredItems(character, addMessage: false) || (character.HasEquippedItem(this) && ic.DrawHudWhenEquipped));
|
||||||
foreach (ItemComponent ic in activeComponents)
|
foreach (ItemComponent ic in activeComponents)
|
||||||
{
|
{
|
||||||
if (ic.HudPriority > 0 && ic.ShouldDrawHUD(character) &&
|
if (ic.HudPriority > 0 && DrawHud(ic) && (maxPriorityHUDs.Count == 0 || ic.HudPriority >= maxPriorityHUDs[0].HudPriority))
|
||||||
(ic.CanBeSelected || (character.HasEquippedItem(this) && ic.DrawHudWhenEquipped)) &&
|
|
||||||
(maxPriorityHUDs.Count == 0 || ic.HudPriority >= maxPriorityHUDs[0].HudPriority))
|
|
||||||
{
|
{
|
||||||
if (maxPriorityHUDs.Count > 0 && ic.HudPriority > maxPriorityHUDs[0].HudPriority) { maxPriorityHUDs.Clear(); }
|
if (maxPriorityHUDs.Count > 0 && ic.HudPriority > maxPriorityHUDs[0].HudPriority) { maxPriorityHUDs.Clear(); }
|
||||||
maxPriorityHUDs.Add(ic);
|
maxPriorityHUDs.Add(ic);
|
||||||
@@ -808,8 +914,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
foreach (ItemComponent ic in activeComponents)
|
foreach (ItemComponent ic in activeComponents)
|
||||||
{
|
{
|
||||||
if (ic.ShouldDrawHUD(character) &&
|
if (DrawHud(ic))
|
||||||
(ic.CanBeSelected || (character.HasEquippedItem(this) && ic.DrawHudWhenEquipped)))
|
|
||||||
{
|
{
|
||||||
activeHUDs.Add(ic);
|
activeHUDs.Add(ic);
|
||||||
}
|
}
|
||||||
@@ -914,11 +1019,11 @@ namespace Barotrauma
|
|||||||
color = Color.Cyan;
|
color = Color.Cyan;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
texts.Add(new ColoredText(ic.DisplayMsg, color, false));
|
texts.Add(new ColoredText(ic.DisplayMsg, color, false, false));
|
||||||
}
|
}
|
||||||
if ((PlayerInput.KeyDown(Keys.LeftShift) || PlayerInput.KeyDown(Keys.RightShift)) && CrewManager.DoesItemHaveContextualOrders(this))
|
if ((PlayerInput.KeyDown(Keys.LeftShift) || PlayerInput.KeyDown(Keys.RightShift)) && CrewManager.DoesItemHaveContextualOrders(this))
|
||||||
{
|
{
|
||||||
texts.Add(new ColoredText(TextManager.ParseInputTypes(TextManager.Get("itemmsgcontextualorders")), Color.Cyan, false));
|
texts.Add(new ColoredText(TextManager.ParseInputTypes(TextManager.Get("itemmsgcontextualorders")), Color.Cyan, false, false));
|
||||||
}
|
}
|
||||||
return texts;
|
return texts;
|
||||||
}
|
}
|
||||||
@@ -1048,6 +1153,29 @@ namespace Barotrauma
|
|||||||
ReadPropertyChange(msg, false);
|
ReadPropertyChange(msg, false);
|
||||||
editingHUDRefreshPending = true;
|
editingHUDRefreshPending = true;
|
||||||
break;
|
break;
|
||||||
|
case NetEntityEvent.Type.Upgrade:
|
||||||
|
{
|
||||||
|
string identifier = msg.ReadString();
|
||||||
|
byte level = msg.ReadByte();
|
||||||
|
if (UpgradePrefab.Find(identifier) is { } upgradePrefab)
|
||||||
|
{
|
||||||
|
Upgrade upgrade = new Upgrade(this, upgradePrefab, level);
|
||||||
|
|
||||||
|
byte targetCount = msg.ReadByte();
|
||||||
|
for (int i = 0; i < targetCount; i++)
|
||||||
|
{
|
||||||
|
byte propertyCount = msg.ReadByte();
|
||||||
|
for (int j = 0; j < propertyCount; j++)
|
||||||
|
{
|
||||||
|
float value = msg.ReadSingle();
|
||||||
|
upgrade.TargetComponents.ElementAt(i).Value[j].SetOriginalValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AddUpgrade(upgrade, false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case NetEntityEvent.Type.Invalid:
|
case NetEntityEvent.Type.Invalid:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1220,7 +1348,7 @@ namespace Barotrauma
|
|||||||
ushort itemId = msg.ReadUInt16();
|
ushort itemId = msg.ReadUInt16();
|
||||||
ushort inventoryId = msg.ReadUInt16();
|
ushort inventoryId = msg.ReadUInt16();
|
||||||
|
|
||||||
DebugConsole.Log("Received entity spawn message for item " + itemName + ".");
|
DebugConsole.Log($"Received entity spawn message for item \"{itemName}\" (identifier: {itemIdentifier}, id: {itemId})");
|
||||||
|
|
||||||
Vector2 pos = Vector2.Zero;
|
Vector2 pos = Vector2.Zero;
|
||||||
Submarine sub = null;
|
Submarine sub = null;
|
||||||
@@ -1243,10 +1371,10 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
byte bodyType = msg.ReadByte();
|
byte bodyType = msg.ReadByte();
|
||||||
|
bool spawnedInOutpost = msg.ReadBoolean();
|
||||||
byte teamID = msg.ReadByte();
|
byte teamID = msg.ReadByte();
|
||||||
bool tagsChanged = msg.ReadBoolean();
|
bool tagsChanged = msg.ReadBoolean();
|
||||||
string tags = "";
|
string tags = "";
|
||||||
if (tagsChanged)
|
if (tagsChanged)
|
||||||
{
|
{
|
||||||
@@ -1289,6 +1417,7 @@ namespace Barotrauma
|
|||||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||||
errorMsg);
|
errorMsg);
|
||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg);
|
||||||
|
inventory = parentItem.GetComponent<ItemContainer>()?.Inventory;
|
||||||
}
|
}
|
||||||
else if (parentItem.components[itemContainerIndex] is ItemContainer container)
|
else if (parentItem.components[itemContainerIndex] is ItemContainer container)
|
||||||
{
|
{
|
||||||
@@ -1307,7 +1436,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
var item = new Item(itemPrefab, pos, sub)
|
var item = new Item(itemPrefab, pos, sub)
|
||||||
{
|
{
|
||||||
ID = itemId
|
ID = itemId,
|
||||||
|
SpawnedInOutpost = spawnedInOutpost
|
||||||
};
|
};
|
||||||
|
|
||||||
if (item.body != null)
|
if (item.body != null)
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Vector2 placeSize = size;
|
Vector2 placeSize = size * Scale;
|
||||||
|
|
||||||
if (placePosition == Vector2.Zero)
|
if (placePosition == Vector2.Zero)
|
||||||
{
|
{
|
||||||
@@ -161,7 +161,14 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sprite?.DrawTiled(spriteBatch, new Vector2(position.X, -position.Y), size, color: SpriteColor);
|
Vector2 placeSize = size * Scale;
|
||||||
|
if (placePosition != Vector2.Zero)
|
||||||
|
{
|
||||||
|
if (ResizeHorizontal) { placeSize.X = Math.Max(position.X - placePosition.X, placeSize.X); }
|
||||||
|
if (ResizeVertical) { placeSize.Y = Math.Max(placePosition.Y - position.Y, placeSize.Y); }
|
||||||
|
position = placePosition;
|
||||||
|
}
|
||||||
|
sprite?.DrawTiled(spriteBatch, new Vector2(position.X, -position.Y), placeSize, color: SpriteColor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,7 +180,15 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (sprite != null) sprite.DrawTiled(spriteBatch, new Vector2(placeRect.X, -placeRect.Y), placeRect.Size.ToVector2(), null, SpriteColor * 0.8f);
|
Vector2 position = Submarine.MouseToWorldGrid(Screen.Selected.Cam, Submarine.MainSub);
|
||||||
|
Vector2 placeSize = size * Scale;
|
||||||
|
if (placePosition != Vector2.Zero)
|
||||||
|
{
|
||||||
|
if (ResizeHorizontal) { placeSize.X = Math.Max(position.X - placePosition.X, placeSize.X); }
|
||||||
|
if (ResizeVertical) { placeSize.Y = Math.Max(placePosition.Y - position.Y, placeSize.Y); }
|
||||||
|
position = placePosition;
|
||||||
|
}
|
||||||
|
sprite?.DrawTiled(spriteBatch, new Vector2(position.X, -position.Y), placeSize, color: SpriteColor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Vector2 dir = IsHorizontal ?
|
Vector2 dir = IsHorizontal ?
|
||||||
new Vector2(Math.Sign(linkedTo[i].Rect.Center.X - rect.Center.X), 0.0f)
|
new Vector2(Math.Sign(linkedTo[i].Rect.Center.X - rect.Center.X), 0.0f)
|
||||||
: new Vector2(0.0f, Math.Sign((linkedTo[i].Rect.Y - linkedTo[i].Rect.Height / 2.0f) - (rect.Y - rect.Height / 2.0f)));
|
: new Vector2(0.0f, Math.Sign((rect.Y - rect.Height / 2.0f) - (linkedTo[i].Rect.Y - linkedTo[i].Rect.Height / 2.0f)));
|
||||||
|
|
||||||
Vector2 arrowPos = new Vector2(WorldRect.Center.X, -(WorldRect.Y - WorldRect.Height / 2));
|
Vector2 arrowPos = new Vector2(WorldRect.Center.X, -(WorldRect.Y - WorldRect.Height / 2));
|
||||||
arrowPos += new Vector2(dir.X * (WorldRect.Width / 2), dir.Y * (WorldRect.Height / 2));
|
arrowPos += new Vector2(dir.X * (WorldRect.Width / 2), dir.Y * (WorldRect.Height / 2));
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ namespace Barotrauma
|
|||||||
for (int i = 1; i < waveY.Length - 1; i++)
|
for (int i = 1; i < waveY.Length - 1; i++)
|
||||||
{
|
{
|
||||||
float maxDelta = Math.Max(Math.Abs(rightDelta[i]), Math.Abs(leftDelta[i]));
|
float maxDelta = Math.Max(Math.Abs(rightDelta[i]), Math.Abs(leftDelta[i]));
|
||||||
if (maxDelta > Rand.Range(1.0f, 10.0f))
|
if (maxDelta > 1.0f && maxDelta > Rand.Range(1.0f, 10.0f))
|
||||||
{
|
{
|
||||||
var particlePos = new Vector2(rect.X + WaveWidth * i, surface + waveY[i]);
|
var particlePos = new Vector2(rect.X + WaveWidth * i, surface + waveY[i]);
|
||||||
if (Submarine != null) particlePos += Submarine.Position;
|
if (Submarine != null) particlePos += Submarine.Position;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
HashSet<Texture2D> uniqueTextures = new HashSet<Texture2D>();
|
HashSet<Texture2D> uniqueTextures = new HashSet<Texture2D>();
|
||||||
HashSet<Sprite> uniqueSprites = new HashSet<Sprite>();
|
HashSet<Sprite> uniqueSprites = new HashSet<Sprite>();
|
||||||
var allLevelObjects = levelObjectManager.GetAllObjects();
|
var allLevelObjects = LevelObjectManager.GetAllObjects();
|
||||||
foreach (var levelObj in allLevelObjects)
|
foreach (var levelObj in allLevelObjects)
|
||||||
{
|
{
|
||||||
foreach (Sprite sprite in levelObj.Prefab.Sprites)
|
foreach (Sprite sprite in levelObj.Prefab.Sprites)
|
||||||
@@ -56,7 +56,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (GameMain.DebugDraw && Screen.Selected.Cam.Zoom > 0.1f)
|
if (GameMain.DebugDraw && Screen.Selected.Cam.Zoom > 0.1f)
|
||||||
{
|
{
|
||||||
foreach (InterestingPosition pos in positionsOfInterest)
|
foreach (InterestingPosition pos in PositionsOfInterest)
|
||||||
{
|
{
|
||||||
Color color = Color.Yellow;
|
Color color = Color.Yellow;
|
||||||
if (pos.PositionType == PositionType.Cave)
|
if (pos.PositionType == PositionType.Cave)
|
||||||
@@ -71,7 +71,7 @@ namespace Barotrauma
|
|||||||
GUI.DrawRectangle(spriteBatch, new Vector2(pos.Position.X - 15.0f, -pos.Position.Y - 15.0f), new Vector2(30.0f, 30.0f), color, true);
|
GUI.DrawRectangle(spriteBatch, new Vector2(pos.Position.X - 15.0f, -pos.Position.Y - 15.0f), new Vector2(30.0f, 30.0f), color, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (RuinGeneration.Ruin ruin in ruins)
|
foreach (RuinGeneration.Ruin ruin in Ruins)
|
||||||
{
|
{
|
||||||
Rectangle ruinArea = ruin.Area;
|
Rectangle ruinArea = ruin.Area;
|
||||||
ruinArea.Y = -ruinArea.Y - ruinArea.Height;
|
ruinArea.Y = -ruinArea.Y - ruinArea.Height;
|
||||||
@@ -113,7 +113,7 @@ namespace Barotrauma
|
|||||||
public void DrawBack(GraphicsDevice graphics, SpriteBatch spriteBatch, Camera cam)
|
public void DrawBack(GraphicsDevice graphics, SpriteBatch spriteBatch, Camera cam)
|
||||||
{
|
{
|
||||||
float brightness = MathHelper.Clamp(1.1f + (cam.Position.Y - Size.Y) / 100000.0f, 0.1f, 1.0f);
|
float brightness = MathHelper.Clamp(1.1f + (cam.Position.Y - Size.Y) / 100000.0f, 0.1f, 1.0f);
|
||||||
var lightColorHLS = generationParams.AmbientLightColor.RgbToHLS();
|
var lightColorHLS = GenerationParams.AmbientLightColor.RgbToHLS();
|
||||||
lightColorHLS.Y *= brightness;
|
lightColorHLS.Y *= brightness;
|
||||||
|
|
||||||
GameMain.LightManager.AmbientLight = ToolBox.HLSToRGB(lightColorHLS);
|
GameMain.LightManager.AmbientLight = ToolBox.HLSToRGB(lightColorHLS);
|
||||||
@@ -121,12 +121,12 @@ namespace Barotrauma
|
|||||||
graphics.Clear(BackgroundColor);
|
graphics.Clear(BackgroundColor);
|
||||||
|
|
||||||
if (renderer == null) return;
|
if (renderer == null) return;
|
||||||
renderer.DrawBackground(spriteBatch, cam, levelObjectManager, backgroundCreatureManager);
|
renderer.DrawBackground(spriteBatch, cam, LevelObjectManager, backgroundCreatureManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
foreach (LevelWall levelWall in extraWalls)
|
foreach (LevelWall levelWall in ExtraWalls)
|
||||||
{
|
{
|
||||||
if (levelWall.Body.BodyType == BodyType.Static) continue;
|
if (levelWall.Body.BodyType == BodyType.Static) continue;
|
||||||
|
|
||||||
|
|||||||
+8
-3
@@ -9,8 +9,12 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
partial class LevelObjectManager
|
partial class LevelObjectManager
|
||||||
{
|
{
|
||||||
private List<LevelObject> visibleObjectsBack = new List<LevelObject>();
|
private readonly List<LevelObject> visibleObjectsBack = new List<LevelObject>();
|
||||||
private List<LevelObject> visibleObjectsFront = new List<LevelObject>();
|
private readonly List<LevelObject> visibleObjectsFront = new List<LevelObject>();
|
||||||
|
|
||||||
|
//Maximum number of visible objects drawn at once. Should be large enough to not have an effect during normal gameplay,
|
||||||
|
//but small enough to prevent wrecking performance when zooming out very far
|
||||||
|
const int MaxVisibleObjects = 500;
|
||||||
|
|
||||||
private Rectangle currentGridIndices;
|
private Rectangle currentGridIndices;
|
||||||
|
|
||||||
@@ -43,7 +47,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
for (int y = currentIndices.Y; y <= currentIndices.Height; y++)
|
for (int y = currentIndices.Y; y <= currentIndices.Height; y++)
|
||||||
{
|
{
|
||||||
if (objectGrid[x, y] == null) continue;
|
if (objectGrid[x, y] == null) { continue; }
|
||||||
foreach (LevelObject obj in objectGrid[x, y])
|
foreach (LevelObject obj in objectGrid[x, y])
|
||||||
{
|
{
|
||||||
var objectList = obj.Position.Z >= 0 ? visibleObjectsBack : visibleObjectsFront;
|
var objectList = obj.Position.Z >= 0 ? visibleObjectsBack : visibleObjectsFront;
|
||||||
@@ -69,6 +73,7 @@ namespace Barotrauma
|
|||||||
if (drawOrderIndex >= 0)
|
if (drawOrderIndex >= 0)
|
||||||
{
|
{
|
||||||
objectList.Insert(drawOrderIndex, obj);
|
objectList.Insert(drawOrderIndex, obj);
|
||||||
|
if (objectList.Count >= MaxVisibleObjects) { break; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ namespace Barotrauma
|
|||||||
level.GenerationParams.WaterParticles.DrawTiled(
|
level.GenerationParams.WaterParticles.DrawTiled(
|
||||||
spriteBatch, origin + offsetS,
|
spriteBatch, origin + offsetS,
|
||||||
new Vector2(cam.WorldView.Width - offsetS.X, cam.WorldView.Height - offsetS.Y),
|
new Vector2(cam.WorldView.Width - offsetS.X, cam.WorldView.Height - offsetS.Y),
|
||||||
rect: srcRect, color: Color.White * alpha, textureScale: new Vector2(texScale));
|
color: Color.White * alpha, textureScale: new Vector2(texScale));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -170,10 +170,12 @@ namespace Barotrauma.Lights
|
|||||||
isHorizontal = BoundingBox.Width > BoundingBox.Height;
|
isHorizontal = BoundingBox.Width > BoundingBox.Height;
|
||||||
if (ParentEntity is Structure structure)
|
if (ParentEntity is Structure structure)
|
||||||
{
|
{
|
||||||
|
System.Diagnostics.Debug.Assert(!structure.Removed);
|
||||||
isHorizontal = structure.IsHorizontal;
|
isHorizontal = structure.IsHorizontal;
|
||||||
}
|
}
|
||||||
else if (ParentEntity is Item item)
|
else if (ParentEntity is Item item)
|
||||||
{
|
{
|
||||||
|
System.Diagnostics.Debug.Assert(!item.Removed);
|
||||||
var door = item.GetComponent<Door>();
|
var door = item.GetComponent<Door>();
|
||||||
if (door != null) { isHorizontal = door.IsHorizontal; }
|
if (door != null) { isHorizontal = door.IsHorizontal; }
|
||||||
}
|
}
|
||||||
@@ -444,7 +446,7 @@ namespace Barotrauma.Lights
|
|||||||
|
|
||||||
CalculateDimensions();
|
CalculateDimensions();
|
||||||
|
|
||||||
if (ParentEntity == null) return;
|
if (ParentEntity == null) { return; }
|
||||||
|
|
||||||
var chList = HullLists.Find(h => h.Submarine == ParentEntity.Submarine);
|
var chList = HullLists.Find(h => h.Submarine == ParentEntity.Submarine);
|
||||||
if (chList != null)
|
if (chList != null)
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ namespace Barotrauma.Lights
|
|||||||
|
|
||||||
private readonly Texture2D visionCircle;
|
private readonly Texture2D visionCircle;
|
||||||
|
|
||||||
|
private Vector2 losOffset;
|
||||||
|
|
||||||
public IEnumerable<LightSource> Lights
|
public IEnumerable<LightSource> Lights
|
||||||
{
|
{
|
||||||
get { return lights; }
|
get { return lights; }
|
||||||
@@ -70,7 +72,7 @@ namespace Barotrauma.Lights
|
|||||||
visionCircle = Sprite.LoadTexture("Content/Lights/visioncircle.png");
|
visionCircle = Sprite.LoadTexture("Content/Lights/visioncircle.png");
|
||||||
highlightRaster = Sprite.LoadTexture("Content/UI/HighlightRaster.png");
|
highlightRaster = Sprite.LoadTexture("Content/UI/HighlightRaster.png");
|
||||||
|
|
||||||
GameMain.Instance.OnResolutionChanged += () =>
|
GameMain.Instance.ResolutionChanged += () =>
|
||||||
{
|
{
|
||||||
CreateRenderTargets(graphics);
|
CreateRenderTargets(graphics);
|
||||||
};
|
};
|
||||||
@@ -279,7 +281,7 @@ namespace Barotrauma.Lights
|
|||||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, effect: SolidColorEffect, transformMatrix: spriteBatchTransform);
|
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, effect: SolidColorEffect, transformMatrix: spriteBatchTransform);
|
||||||
foreach (Character character in Character.CharacterList)
|
foreach (Character character in Character.CharacterList)
|
||||||
{
|
{
|
||||||
if (character.CurrentHull == null || !character.Enabled) { continue; }
|
if (character.CurrentHull == null || !character.Enabled || !character.IsVisible) { continue; }
|
||||||
if (Character.Controlled?.FocusedCharacter == character) { continue; }
|
if (Character.Controlled?.FocusedCharacter == character) { continue; }
|
||||||
Color lightColor = character.CurrentHull.AmbientLight == Color.TransparentBlack ?
|
Color lightColor = character.CurrentHull.AmbientLight == Color.TransparentBlack ?
|
||||||
Color.Black :
|
Color.Black :
|
||||||
@@ -297,7 +299,7 @@ namespace Barotrauma.Lights
|
|||||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, transformMatrix: spriteBatchTransform);
|
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, transformMatrix: spriteBatchTransform);
|
||||||
foreach (Character character in Character.CharacterList)
|
foreach (Character character in Character.CharacterList)
|
||||||
{
|
{
|
||||||
if (character.CurrentHull == null || !character.Enabled) { continue; }
|
if (character.CurrentHull == null || !character.Enabled || !character.IsVisible) { continue; }
|
||||||
if (Character.Controlled?.FocusedCharacter == character) { continue; }
|
if (Character.Controlled?.FocusedCharacter == character) { continue; }
|
||||||
Color lightColor = character.CurrentHull.AmbientLight == Color.TransparentBlack ?
|
Color lightColor = character.CurrentHull.AmbientLight == Color.TransparentBlack ?
|
||||||
Color.Black :
|
Color.Black :
|
||||||
@@ -335,7 +337,20 @@ namespace Barotrauma.Lights
|
|||||||
|
|
||||||
if (Character.Controlled != null)
|
if (Character.Controlled != null)
|
||||||
{
|
{
|
||||||
Vector2 haloDrawPos = Character.Controlled.DrawPosition;
|
DrawHalo(Character.Controlled);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (Character character in Character.CharacterList)
|
||||||
|
{
|
||||||
|
if (character.Submarine == null || character.IsDead || !character.IsHuman) { continue; }
|
||||||
|
DrawHalo(character);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawHalo(Character character)
|
||||||
|
{
|
||||||
|
Vector2 haloDrawPos = character.DrawPosition;
|
||||||
haloDrawPos.Y = -haloDrawPos.Y;
|
haloDrawPos.Y = -haloDrawPos.Y;
|
||||||
|
|
||||||
//ambient light decreases the brightness of the halo (no need for a bright halo if the ambient light is bright enough)
|
//ambient light decreases the brightness of the halo (no need for a bright halo if the ambient light is bright enough)
|
||||||
@@ -349,6 +364,7 @@ namespace Barotrauma.Lights
|
|||||||
new Vector2(LightSource.LightTexture.Width, LightSource.LightTexture.Height) / 2, scale, SpriteEffects.None, 0.0f);
|
new Vector2(LightSource.LightTexture.Width, LightSource.LightTexture.Height) / 2, scale, SpriteEffects.None, 0.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
|
|
||||||
//draw the actual light volumes, additive particles, hull ambient lights and the halo around the player
|
//draw the actual light volumes, additive particles, hull ambient lights and the halo around the player
|
||||||
@@ -477,10 +493,11 @@ namespace Barotrauma.Lights
|
|||||||
graphics.Clear(Color.Black);
|
graphics.Clear(Color.Black);
|
||||||
Vector2 diff = lookAtPosition - ViewTarget.WorldPosition;
|
Vector2 diff = lookAtPosition - ViewTarget.WorldPosition;
|
||||||
diff.Y = -diff.Y;
|
diff.Y = -diff.Y;
|
||||||
float rotation = MathUtils.VectorToAngle(diff);
|
if (diff.LengthSquared() > 30.0f) { losOffset = diff; }
|
||||||
|
float rotation = MathUtils.VectorToAngle(losOffset);
|
||||||
|
|
||||||
Vector2 scale = new Vector2(
|
Vector2 scale = new Vector2(
|
||||||
MathHelper.Clamp(diff.Length() / 256.0f, 2.0f, 5.0f), 2.0f);
|
MathHelper.Clamp(losOffset.Length() / 256.0f, 2.0f, 5.0f), 2.0f);
|
||||||
|
|
||||||
spriteBatch.Draw(visionCircle, new Vector2(ViewTarget.WorldPosition.X, -ViewTarget.WorldPosition.Y), null, Color.White, rotation,
|
spriteBatch.Draw(visionCircle, new Vector2(ViewTarget.WorldPosition.X, -ViewTarget.WorldPosition.Y), null, Color.White, rotation,
|
||||||
new Vector2(visionCircle.Width * 0.2f, visionCircle.Height / 2), scale, SpriteEffects.None, 0.0f);
|
new Vector2(visionCircle.Width * 0.2f, visionCircle.Height / 2), scale, SpriteEffects.None, 0.0f);
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Barotrauma
|
|
||||||
{
|
|
||||||
partial class Location
|
|
||||||
{
|
|
||||||
private HireManager hireManager;
|
|
||||||
|
|
||||||
public void RemoveHireableCharacter(CharacterInfo character)
|
|
||||||
{
|
|
||||||
if (!Type.HasHireableCharacters)
|
|
||||||
{
|
|
||||||
DebugConsole.ThrowError("Cannot hire a character from location \"" + Name + "\" - the location has no hireable characters.\n" + Environment.StackTrace);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (hireManager == null)
|
|
||||||
{
|
|
||||||
DebugConsole.ThrowError("Cannot hire a character from location \"" + Name + "\" - hire manager has not been instantiated.\n" + Environment.StackTrace);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
hireManager.RemoveCharacter(character);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<CharacterInfo> GetHireableCharacters()
|
|
||||||
{
|
|
||||||
if (!Type.HasHireableCharacters)
|
|
||||||
{
|
|
||||||
return Enumerable.Empty<CharacterInfo>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hireManager == null)
|
|
||||||
{
|
|
||||||
hireManager = new HireManager();
|
|
||||||
}
|
|
||||||
if (!hireManager.AvailableCharacters.Any())
|
|
||||||
{
|
|
||||||
hireManager.GenerateCharacters(location: this, amount: HireManager.MaxAvailableCharacters);
|
|
||||||
}
|
|
||||||
return hireManager.AvailableCharacters;
|
|
||||||
}
|
|
||||||
|
|
||||||
partial void RemoveProjSpecific()
|
|
||||||
{
|
|
||||||
hireManager?.Remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,14 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
abstract partial class MapEntityPrefab : IPrefab, IDisposable
|
abstract partial class MapEntityPrefab : IPrefab, IDisposable
|
||||||
{
|
{
|
||||||
|
public readonly Dictionary<string, List<DecorativeSprite>> UpgradeOverrideSprites = new Dictionary<string, List<DecorativeSprite>>();
|
||||||
|
|
||||||
public virtual void UpdatePlacing(Camera cam)
|
public virtual void UpdatePlacing(Camera cam)
|
||||||
{
|
{
|
||||||
if (PlayerInput.SecondaryMouseButtonClicked())
|
if (PlayerInput.SecondaryMouseButtonClicked())
|
||||||
|
|||||||
@@ -95,6 +95,22 @@ namespace Barotrauma
|
|||||||
GUIListBox listBox = new GUIListBox(new RectTransform(new Vector2(0.95f, 0.8f), editingHUD.RectTransform, Anchor.Center), style: null);
|
GUIListBox listBox = new GUIListBox(new RectTransform(new Vector2(0.95f, 0.8f), editingHUD.RectTransform, Anchor.Center), style: null);
|
||||||
var editor = new SerializableEntityEditor(listBox.Content.RectTransform, this, inGame, showName: true, titleFont: GUI.LargeFont);
|
var editor = new SerializableEntityEditor(listBox.Content.RectTransform, this, inGame, showName: true, titleFont: GUI.LargeFont);
|
||||||
|
|
||||||
|
if (Submarine.MainSub?.Info?.Type == SubmarineType.OutpostModule)
|
||||||
|
{
|
||||||
|
GUITickBox tickBox = new GUITickBox(new RectTransform(new Point(listBox.Content.Rect.Width, 10)), TextManager.Get("sp.structure.removeiflinkedoutpostdoorinuse.name"))
|
||||||
|
{
|
||||||
|
Font = GUI.SmallFont,
|
||||||
|
Selected = RemoveIfLinkedOutpostDoorInUse,
|
||||||
|
ToolTip = TextManager.Get("sp.structure.removeiflinkedoutpostdoorinuse.description"),
|
||||||
|
OnSelected = (tickBox) =>
|
||||||
|
{
|
||||||
|
RemoveIfLinkedOutpostDoorInUse = tickBox.Selected;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
editor.AddCustomContent(tickBox, 1);
|
||||||
|
}
|
||||||
|
|
||||||
var buttonContainer = new GUILayoutGroup(new RectTransform(new Point(listBox.Content.Rect.Width, heightScaled)), isHorizontal: true)
|
var buttonContainer = new GUILayoutGroup(new RectTransform(new Point(listBox.Content.Rect.Width, heightScaled)), isHorizontal: true)
|
||||||
{
|
{
|
||||||
Stretch = true,
|
Stretch = true,
|
||||||
@@ -261,7 +277,7 @@ namespace Barotrauma
|
|||||||
SpriteEffects oldEffects = Prefab.BackgroundSprite.effects;
|
SpriteEffects oldEffects = Prefab.BackgroundSprite.effects;
|
||||||
Prefab.BackgroundSprite.effects ^= SpriteEffects;
|
Prefab.BackgroundSprite.effects ^= SpriteEffects;
|
||||||
|
|
||||||
Point backGroundOffset = new Point(
|
Vector2 backGroundOffset = new Vector2(
|
||||||
MathUtils.PositiveModulo((int)-textureOffset.X, Prefab.BackgroundSprite.SourceRect.Width),
|
MathUtils.PositiveModulo((int)-textureOffset.X, Prefab.BackgroundSprite.SourceRect.Width),
|
||||||
MathUtils.PositiveModulo((int)-textureOffset.Y, Prefab.BackgroundSprite.SourceRect.Height));
|
MathUtils.PositiveModulo((int)-textureOffset.Y, Prefab.BackgroundSprite.SourceRect.Height));
|
||||||
|
|
||||||
@@ -299,7 +315,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (damageEffect != null)
|
if (damageEffect != null)
|
||||||
{
|
{
|
||||||
float newCutoff = MathHelper.Lerp(0.0f, 0.65f, Sections[i].damage / Prefab.Health);
|
float newCutoff = MathHelper.Lerp(0.0f, 0.65f, Sections[i].damage / MaxHealth);
|
||||||
|
|
||||||
if (Math.Abs(newCutoff - Submarine.DamageEffectCutoff) > 0.01f || color != Submarine.DamageEffectColor)
|
if (Math.Abs(newCutoff - Submarine.DamageEffectCutoff) > 0.01f || color != Submarine.DamageEffectColor)
|
||||||
{
|
{
|
||||||
@@ -314,7 +330,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Point sectionOffset = new Point(
|
Vector2 sectionOffset = new Vector2(
|
||||||
Math.Abs(rect.Location.X - Sections[i].rect.Location.X),
|
Math.Abs(rect.Location.X - Sections[i].rect.Location.X),
|
||||||
Math.Abs(rect.Location.Y - Sections[i].rect.Location.Y));
|
Math.Abs(rect.Location.Y - Sections[i].rect.Location.Y));
|
||||||
|
|
||||||
@@ -371,7 +387,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
var textPos = SectionPosition(i, true);
|
var textPos = SectionPosition(i, true);
|
||||||
textPos.Y = -textPos.Y;
|
textPos.Y = -textPos.Y;
|
||||||
GUI.DrawString(spriteBatch, textPos, "Damage: " + (int)((GetSection(i).damage / Health) * 100f) + "%", Color.Yellow);
|
GUI.DrawString(spriteBatch, textPos, "Damage: " + (int)((GetSection(i).damage / MaxHealth) * 100f) + "%", Color.Yellow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -448,7 +464,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
for (int i = 0; i < sectionCount; i++)
|
for (int i = 0; i < sectionCount; i++)
|
||||||
{
|
{
|
||||||
float damage = msg.ReadRangedSingle(0.0f, 1.0f, 8) * Health;
|
float damage = msg.ReadRangedSingle(0.0f, 1.0f, 8) * MaxHealth;
|
||||||
if (i < Sections.Length)
|
if (i < Sections.Length)
|
||||||
{
|
{
|
||||||
SetDamage(i, damage);
|
SetDamage(i, damage);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using FarseerPhysics;
|
|||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Barotrauma.IO;
|
using Barotrauma.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -306,8 +307,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public static void DrawGrid(SpriteBatch spriteBatch, int gridCells, Vector2 gridCenter, Vector2 roundedGridCenter, float alpha = 1.0f)
|
public static void DrawGrid(SpriteBatch spriteBatch, int gridCells, Vector2 gridCenter, Vector2 roundedGridCenter, float alpha = 1.0f)
|
||||||
{
|
{
|
||||||
var horizontalLine = GUI.Style.GetComponentStyle("HorizontalLine").Sprites[GUIComponent.ComponentState.None].First();
|
var horizontalLine = GUI.Style.GetComponentStyle("HorizontalLine").GetDefaultSprite();
|
||||||
var verticalLine = GUI.Style.GetComponentStyle("VerticalLine").Sprites[GUIComponent.ComponentState.None].First();
|
var verticalLine = GUI.Style.GetComponentStyle("VerticalLine").GetDefaultSprite();
|
||||||
|
|
||||||
Vector2 topLeft = roundedGridCenter - Vector2.One * GridSize * gridCells / 2;
|
Vector2 topLeft = roundedGridCenter - Vector2.One * GridSize * gridCells / 2;
|
||||||
Vector2 bottomRight = roundedGridCenter + Vector2.One * GridSize * gridCells / 2;
|
Vector2 bottomRight = roundedGridCenter + Vector2.One * GridSize * gridCells / 2;
|
||||||
@@ -324,19 +325,19 @@ namespace Barotrauma
|
|||||||
float expandY = MathHelper.Lerp(30.0f, 0.0f, normalizedDistY);
|
float expandY = MathHelper.Lerp(30.0f, 0.0f, normalizedDistY);
|
||||||
|
|
||||||
GUI.DrawLine(spriteBatch,
|
GUI.DrawLine(spriteBatch,
|
||||||
horizontalLine.Sprite,
|
horizontalLine,
|
||||||
new Vector2(topLeft.X - expandX, -bottomRight.Y + i * GridSize.Y),
|
new Vector2(topLeft.X - expandX, -bottomRight.Y + i * GridSize.Y),
|
||||||
new Vector2(bottomRight.X + expandX, -bottomRight.Y + i * GridSize.Y),
|
new Vector2(bottomRight.X + expandX, -bottomRight.Y + i * GridSize.Y),
|
||||||
Color.White * (1.0f - normalizedDistY) * alpha, depth: 0.6f, width: 3);
|
Color.White * (1.0f - normalizedDistY) * alpha, depth: 0.6f, width: 3);
|
||||||
GUI.DrawLine(spriteBatch,
|
GUI.DrawLine(spriteBatch,
|
||||||
verticalLine.Sprite,
|
verticalLine,
|
||||||
new Vector2(topLeft.X + i * GridSize.X, -topLeft.Y + expandY),
|
new Vector2(topLeft.X + i * GridSize.X, -topLeft.Y + expandY),
|
||||||
new Vector2(topLeft.X + i * GridSize.X, -bottomRight.Y - expandY),
|
new Vector2(topLeft.X + i * GridSize.X, -bottomRight.Y - expandY),
|
||||||
Color.White * (1.0f - normalizedDistX) * alpha, depth: 0.6f, width: 3);
|
Color.White * (1.0f - normalizedDistX) * alpha, depth: 0.6f, width: 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CreateMiniMap(GUIComponent parent, IEnumerable<Entity> pointsOfInterest = null)
|
public void CreateMiniMap(GUIComponent parent, IEnumerable<Entity> pointsOfInterest = null, bool ignoreOutpost = false)
|
||||||
{
|
{
|
||||||
Rectangle worldBorders = GetDockedBorders();
|
Rectangle worldBorders = GetDockedBorders();
|
||||||
worldBorders.Location += WorldPosition.ToPoint();
|
worldBorders.Location += WorldPosition.ToPoint();
|
||||||
@@ -354,7 +355,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
foreach (Hull hull in Hull.hullList)
|
foreach (Hull hull in Hull.hullList)
|
||||||
{
|
{
|
||||||
if (hull.Submarine != this && !DockedTo.Contains(hull.Submarine)) continue;
|
if (hull.Submarine != this && !(DockedTo.Contains(hull.Submarine))) continue;
|
||||||
|
if (ignoreOutpost && !IsEntityFoundOnThisSub(hull, true)) { continue; }
|
||||||
|
|
||||||
Vector2 relativeHullPos = new Vector2(
|
Vector2 relativeHullPos = new Vector2(
|
||||||
(hull.WorldRect.X - worldBorders.X) / (float)worldBorders.Width,
|
(hull.WorldRect.X - worldBorders.X) / (float)worldBorders.Width,
|
||||||
@@ -393,35 +395,61 @@ namespace Barotrauma
|
|||||||
errorMsgs.Add(TextManager.Get("NoHullsWarning"));
|
errorMsgs.Add(TextManager.Get("NoHullsWarning"));
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Item item in Item.ItemList)
|
if (Info.Type != SubmarineType.OutpostModule ||
|
||||||
|
(Info.OutpostModuleInfo?.ModuleFlags.Any(f => !f.Equals("hallwayvertical", StringComparison.OrdinalIgnoreCase) && !f.Equals("hallwayhorizontal", StringComparison.OrdinalIgnoreCase)) ?? true))
|
||||||
{
|
{
|
||||||
if (item.GetComponent<Items.Components.Vent>() == null) continue;
|
if (!WayPoint.WayPointList.Any(wp => wp.ShouldBeSaved && wp.SpawnType == SpawnType.Path))
|
||||||
|
|
||||||
if (!item.linkedTo.Any())
|
|
||||||
{
|
{
|
||||||
errorMsgs.Add(TextManager.Get("DisconnectedVentsWarning"));
|
errorMsgs.Add(TextManager.Get("NoWaypointsWarning"));
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!WayPoint.WayPointList.Any(wp => wp.ShouldBeSaved && wp.SpawnType == SpawnType.Human))
|
if (Info.Type == SubmarineType.Player)
|
||||||
{
|
{
|
||||||
errorMsgs.Add(TextManager.Get("NoHumanSpawnpointWarning"));
|
foreach (Item item in Item.ItemList)
|
||||||
}
|
{
|
||||||
|
if (item.GetComponent<Items.Components.Vent>() == null) { continue; }
|
||||||
|
if (!item.linkedTo.Any())
|
||||||
|
{
|
||||||
|
errorMsgs.Add(TextManager.Get("DisconnectedVentsWarning"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!WayPoint.WayPointList.Any(wp => wp.ShouldBeSaved && wp.SpawnType == SpawnType.Path))
|
if (!WayPoint.WayPointList.Any(wp => wp.ShouldBeSaved && wp.SpawnType == SpawnType.Human))
|
||||||
{
|
{
|
||||||
errorMsgs.Add(TextManager.Get("NoWaypointsWarning"));
|
errorMsgs.Add(TextManager.Get("NoHumanSpawnpointWarning"));
|
||||||
|
}
|
||||||
|
if (WayPoint.WayPointList.Find(wp => wp.SpawnType == SpawnType.Cargo) == null)
|
||||||
|
{
|
||||||
|
errorMsgs.Add(TextManager.Get("NoCargoSpawnpointWarning"));
|
||||||
|
}
|
||||||
|
if (!Item.ItemList.Any(it => it.GetComponent<Items.Components.Pump>() != null && it.HasTag("ballast")))
|
||||||
|
{
|
||||||
|
errorMsgs.Add(TextManager.Get("NoBallastTagsWarning"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else if (Info.Type == SubmarineType.OutpostModule)
|
||||||
if (WayPoint.WayPointList.Find(wp => wp.SpawnType == SpawnType.Cargo) == null)
|
|
||||||
{
|
{
|
||||||
errorMsgs.Add(TextManager.Get("NoCargoSpawnpointWarning"));
|
foreach (Item item in Item.ItemList)
|
||||||
}
|
{
|
||||||
|
var junctionBox = item.GetComponent<PowerTransfer>();
|
||||||
if (!Item.ItemList.Any(it => it.GetComponent<Items.Components.Pump>() != null && it.HasTag("ballast")))
|
if (junctionBox == null) { continue; }
|
||||||
{
|
int doorLinks =
|
||||||
errorMsgs.Add(TextManager.Get("NoBallastTagsWarning"));
|
item.linkedTo.Count(lt => lt is Gap || (lt is Item it2 && it2.GetComponent<Door>() != null)) +
|
||||||
|
Item.ItemList.Count(it2 => it2.linkedTo.Contains(item) && !item.linkedTo.Contains(it2));
|
||||||
|
for (int i = 0; i < item.Connections.Count; i++)
|
||||||
|
{
|
||||||
|
int wireCount = item.Connections[i].Wires.Count(w => w != null);
|
||||||
|
if (doorLinks + wireCount > Connection.MaxLinked)
|
||||||
|
{
|
||||||
|
errorMsgs.Add(TextManager.GetWithVariables("InsufficientFreeConnectionsWarning",
|
||||||
|
new string[] { "[doorcount]", "[freeconnectioncount]" },
|
||||||
|
new string[] { doorLinks.ToString(), (Connection.MaxLinked - wireCount).ToString() }));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Gap.GapList.Any(g => g.linkedTo.Count == 0))
|
if (Gap.GapList.Any(g => g.linkedTo.Count == 0))
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using Barotrauma.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Xml.Linq;
|
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -58,77 +54,9 @@ namespace Barotrauma
|
|||||||
Spacing = 5
|
Spacing = 5
|
||||||
};
|
};
|
||||||
|
|
||||||
//space
|
ScalableFont font = parent.Rect.Width < 350 ? GUI.SmallFont : GUI.Font;
|
||||||
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.03f), descriptionBox.Content.RectTransform), style: null);
|
|
||||||
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1, 0), descriptionBox.Content.RectTransform), TextManager.Get("submarine.name." + Name, true) ?? Name, font: GUI.LargeFont, wrap: true) { ForceUpperCase = true, CanBeFocused = false };
|
CreateSpecsWindow(descriptionBox, font);
|
||||||
|
|
||||||
float leftPanelWidth = 0.6f;
|
|
||||||
float rightPanelWidth = 0.4f / leftPanelWidth;
|
|
||||||
|
|
||||||
ScalableFont font = descriptionBox.Rect.Width < 350 ? GUI.SmallFont : GUI.Font;
|
|
||||||
|
|
||||||
Vector2 realWorldDimensions = Dimensions * Physics.DisplayToRealWorldRatio;
|
|
||||||
if (realWorldDimensions != Vector2.Zero)
|
|
||||||
{
|
|
||||||
string dimensionsStr = TextManager.GetWithVariables("DimensionsFormat", new string[2] { "[width]", "[height]" }, new string[2] { ((int)realWorldDimensions.X).ToString(), ((int)realWorldDimensions.Y).ToString() });
|
|
||||||
|
|
||||||
var dimensionsText = new GUITextBlock(new RectTransform(new Vector2(leftPanelWidth, 0), descriptionBox.Content.RectTransform),
|
|
||||||
TextManager.Get("Dimensions"), textAlignment: Alignment.TopLeft, font: font, wrap: true)
|
|
||||||
{ CanBeFocused = false };
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(rightPanelWidth, 0.0f), dimensionsText.RectTransform, Anchor.TopRight, Pivot.TopLeft),
|
|
||||||
dimensionsStr, textAlignment: Alignment.TopLeft, font: font, wrap: true)
|
|
||||||
{ CanBeFocused = false };
|
|
||||||
dimensionsText.RectTransform.MinSize = new Point(0, dimensionsText.Children.First().Rect.Height);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RecommendedCrewSizeMax > 0)
|
|
||||||
{
|
|
||||||
var crewSizeText = new GUITextBlock(new RectTransform(new Vector2(leftPanelWidth, 0), descriptionBox.Content.RectTransform),
|
|
||||||
TextManager.Get("RecommendedCrewSize"), textAlignment: Alignment.TopLeft, font: font, wrap: true)
|
|
||||||
{ CanBeFocused = false };
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(rightPanelWidth, 0.0f), crewSizeText.RectTransform, Anchor.TopRight, Pivot.TopLeft),
|
|
||||||
RecommendedCrewSizeMin + " - " + RecommendedCrewSizeMax, textAlignment: Alignment.TopLeft, font: font, wrap: true)
|
|
||||||
{ CanBeFocused = false };
|
|
||||||
crewSizeText.RectTransform.MinSize = new Point(0, crewSizeText.Children.First().Rect.Height);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(RecommendedCrewExperience))
|
|
||||||
{
|
|
||||||
var crewExperienceText = new GUITextBlock(new RectTransform(new Vector2(leftPanelWidth, 0), descriptionBox.Content.RectTransform),
|
|
||||||
TextManager.Get("RecommendedCrewExperience"), textAlignment: Alignment.TopLeft, font: font, wrap: true)
|
|
||||||
{ CanBeFocused = false };
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(rightPanelWidth, 0.0f), crewExperienceText.RectTransform, Anchor.TopRight, Pivot.TopLeft),
|
|
||||||
TextManager.Get(RecommendedCrewExperience), textAlignment: Alignment.TopLeft, font: font, wrap: true)
|
|
||||||
{ CanBeFocused = false };
|
|
||||||
crewExperienceText.RectTransform.MinSize = new Point(0, crewExperienceText.Children.First().Rect.Height);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RequiredContentPackages.Any())
|
|
||||||
{
|
|
||||||
var contentPackagesText = new GUITextBlock(new RectTransform(new Vector2(leftPanelWidth, 0), descriptionBox.Content.RectTransform),
|
|
||||||
TextManager.Get("RequiredContentPackages"), textAlignment: Alignment.TopLeft, font: font)
|
|
||||||
{ CanBeFocused = false };
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(rightPanelWidth, 0.0f), contentPackagesText.RectTransform, Anchor.TopRight, Pivot.TopLeft),
|
|
||||||
string.Join(", ", RequiredContentPackages), textAlignment: Alignment.TopLeft, font: font, wrap: true)
|
|
||||||
{ CanBeFocused = false };
|
|
||||||
contentPackagesText.RectTransform.MinSize = new Point(0, contentPackagesText.Children.First().Rect.Height);
|
|
||||||
}
|
|
||||||
|
|
||||||
// show what game version the submarine was created on
|
|
||||||
if (!IsVanillaSubmarine() && GameVersion != null)
|
|
||||||
{
|
|
||||||
var versionText = new GUITextBlock(new RectTransform(new Vector2(leftPanelWidth, 0), descriptionBox.Content.RectTransform),
|
|
||||||
TextManager.Get("serverlistversion"), textAlignment: Alignment.TopLeft, font: font, wrap: true)
|
|
||||||
{ CanBeFocused = false };
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(rightPanelWidth, 0.0f), versionText.RectTransform, Anchor.TopRight, Pivot.TopLeft),
|
|
||||||
GameVersion.ToString(), textAlignment: Alignment.TopLeft, font: font, wrap: true)
|
|
||||||
{ CanBeFocused = false };
|
|
||||||
|
|
||||||
versionText.RectTransform.MinSize = new Point(0, versionText.Children.First().Rect.Height);
|
|
||||||
}
|
|
||||||
|
|
||||||
GUITextBlock.AutoScaleAndNormalize(descriptionBox.Content.Children.Where(c => c is GUITextBlock).Cast<GUITextBlock>());
|
|
||||||
|
|
||||||
//space
|
//space
|
||||||
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), descriptionBox.Content.RectTransform), style: null);
|
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), descriptionBox.Content.RectTransform), style: null);
|
||||||
@@ -145,5 +73,84 @@ namespace Barotrauma
|
|||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CreateSpecsWindow(GUIListBox parent, ScalableFont font)
|
||||||
|
{
|
||||||
|
float leftPanelWidth = 0.6f;
|
||||||
|
float rightPanelWidth = 0.4f / leftPanelWidth;
|
||||||
|
string className = !HasTag(SubmarineTag.Shuttle) ? TextManager.Get($"submarineclass.{SubmarineClass}") : TextManager.Get("shuttle");
|
||||||
|
|
||||||
|
int nameHeight = (int)GUI.LargeFont.MeasureString(DisplayName, true).Y;
|
||||||
|
int classHeight = (int)GUI.SubHeadingFont.MeasureString(className).Y;
|
||||||
|
int leftPanelWidthInt = (int)(parent.Rect.Width * leftPanelWidth);
|
||||||
|
|
||||||
|
var submarineNameText = new GUITextBlock(new RectTransform(new Point(leftPanelWidthInt, nameHeight + HUDLayoutSettings.Padding / 2), parent.Content.RectTransform), DisplayName, textAlignment: Alignment.CenterLeft, font: GUI.LargeFont) { CanBeFocused = false };
|
||||||
|
submarineNameText.RectTransform.MinSize = new Point(0, (int)submarineNameText.TextSize.Y);
|
||||||
|
var submarineClassText = new GUITextBlock(new RectTransform(new Point(leftPanelWidthInt, classHeight), parent.Content.RectTransform), className, textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont) { CanBeFocused = false };
|
||||||
|
submarineClassText.RectTransform.MinSize = new Point(0, (int)submarineClassText.TextSize.Y);
|
||||||
|
|
||||||
|
Vector2 realWorldDimensions = Dimensions * Physics.DisplayToRealWorldRatio;
|
||||||
|
if (realWorldDimensions != Vector2.Zero)
|
||||||
|
{
|
||||||
|
string dimensionsStr = TextManager.GetWithVariables("DimensionsFormat", new string[2] { "[width]", "[height]" }, new string[2] { ((int)realWorldDimensions.X).ToString(), ((int)realWorldDimensions.Y).ToString() });
|
||||||
|
|
||||||
|
var dimensionsText = new GUITextBlock(new RectTransform(new Vector2(leftPanelWidth, 0), parent.Content.RectTransform),
|
||||||
|
TextManager.Get("Dimensions"), textAlignment: Alignment.TopLeft, font: font, wrap: true)
|
||||||
|
{ CanBeFocused = false };
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(rightPanelWidth, 0.0f), dimensionsText.RectTransform, Anchor.TopRight, Pivot.TopLeft),
|
||||||
|
dimensionsStr, textAlignment: Alignment.TopLeft, font: font, wrap: true)
|
||||||
|
{ CanBeFocused = false };
|
||||||
|
dimensionsText.RectTransform.MinSize = new Point(0, dimensionsText.Children.First().Rect.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RecommendedCrewSizeMax > 0)
|
||||||
|
{
|
||||||
|
var crewSizeText = new GUITextBlock(new RectTransform(new Vector2(leftPanelWidth, 0), parent.Content.RectTransform),
|
||||||
|
TextManager.Get("RecommendedCrewSize"), textAlignment: Alignment.TopLeft, font: font, wrap: true)
|
||||||
|
{ CanBeFocused = false };
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(rightPanelWidth, 0.0f), crewSizeText.RectTransform, Anchor.TopRight, Pivot.TopLeft),
|
||||||
|
RecommendedCrewSizeMin + " - " + RecommendedCrewSizeMax, textAlignment: Alignment.TopLeft, font: font, wrap: true)
|
||||||
|
{ CanBeFocused = false };
|
||||||
|
crewSizeText.RectTransform.MinSize = new Point(0, crewSizeText.Children.First().Rect.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(RecommendedCrewExperience))
|
||||||
|
{
|
||||||
|
var crewExperienceText = new GUITextBlock(new RectTransform(new Vector2(leftPanelWidth, 0), parent.Content.RectTransform),
|
||||||
|
TextManager.Get("RecommendedCrewExperience"), textAlignment: Alignment.TopLeft, font: font, wrap: true)
|
||||||
|
{ CanBeFocused = false };
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(rightPanelWidth, 0.0f), crewExperienceText.RectTransform, Anchor.TopRight, Pivot.TopLeft),
|
||||||
|
TextManager.Get(RecommendedCrewExperience), textAlignment: Alignment.TopLeft, font: font, wrap: true)
|
||||||
|
{ CanBeFocused = false };
|
||||||
|
crewExperienceText.RectTransform.MinSize = new Point(0, crewExperienceText.Children.First().Rect.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RequiredContentPackages.Any())
|
||||||
|
{
|
||||||
|
var contentPackagesText = new GUITextBlock(new RectTransform(new Vector2(leftPanelWidth, 0), parent.Content.RectTransform),
|
||||||
|
TextManager.Get("RequiredContentPackages"), textAlignment: Alignment.TopLeft, font: font)
|
||||||
|
{ CanBeFocused = false };
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(rightPanelWidth, 0.0f), contentPackagesText.RectTransform, Anchor.TopRight, Pivot.TopLeft),
|
||||||
|
string.Join(", ", RequiredContentPackages), textAlignment: Alignment.TopLeft, font: font, wrap: true)
|
||||||
|
{ CanBeFocused = false };
|
||||||
|
contentPackagesText.RectTransform.MinSize = new Point(0, contentPackagesText.Children.First().Rect.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// show what game version the submarine was created on
|
||||||
|
if (!IsVanillaSubmarine() && GameVersion != null)
|
||||||
|
{
|
||||||
|
var versionText = new GUITextBlock(new RectTransform(new Vector2(leftPanelWidth, 0), parent.Content.RectTransform),
|
||||||
|
TextManager.Get("serverlistversion"), textAlignment: Alignment.TopLeft, font: font, wrap: true)
|
||||||
|
{ CanBeFocused = false };
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(rightPanelWidth, 0.0f), versionText.RectTransform, Anchor.TopRight, Pivot.TopLeft),
|
||||||
|
GameVersion.ToString(), textAlignment: Alignment.TopLeft, font: font, wrap: true)
|
||||||
|
{ CanBeFocused = false };
|
||||||
|
|
||||||
|
versionText.RectTransform.MinSize = new Point(0, versionText.Children.First().Rect.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
submarineNameText.AutoScaleHorizontal = true;
|
||||||
|
GUITextBlock.AutoScaleAndNormalize(parent.Content.Children.Where(c => c is GUITextBlock && c != submarineNameText).Cast<GUITextBlock>());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user