38f1ddb...178a853: v0.8.9.1, removed content folder
This commit is contained in:
@@ -15,10 +15,10 @@ namespace Barotrauma.Items.Components
|
||||
private Vector2[] GetConvexHullCorners(Rectangle rect)
|
||||
{
|
||||
Vector2[] corners = new Vector2[4];
|
||||
corners[0] = new Vector2(rect.X, rect.Y - rect.Height);
|
||||
corners[1] = new Vector2(rect.X, rect.Y);
|
||||
corners[2] = new Vector2(rect.Right, rect.Y);
|
||||
corners[3] = new Vector2(rect.Right, rect.Y - rect.Height);
|
||||
corners[0] = new Vector2(rect.X - 1, rect.Y - rect.Height - 1);
|
||||
corners[1] = new Vector2(rect.X - 1, rect.Y + 1);
|
||||
corners[2] = new Vector2(rect.Right + 1, rect.Y + 1);
|
||||
corners[3] = new Vector2(rect.Right + 1, rect.Y - rect.Height - 1);
|
||||
|
||||
return corners;
|
||||
}
|
||||
@@ -26,10 +26,10 @@ namespace Barotrauma.Items.Components
|
||||
private void UpdateConvexHulls()
|
||||
{
|
||||
doorRect = new Rectangle(
|
||||
item.Rect.Center.X - (int)(doorSprite.size.X / 2),
|
||||
item.Rect.Y - item.Rect.Height / 2 + (int)(doorSprite.size.Y / 2.0f),
|
||||
(int)doorSprite.size.X,
|
||||
(int)doorSprite.size.Y);
|
||||
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),
|
||||
(int)(doorSprite.size.X * item.Scale),
|
||||
(int)(doorSprite.size.Y * item.Scale));
|
||||
|
||||
Rectangle rect = doorRect;
|
||||
if (isHorizontal)
|
||||
@@ -43,7 +43,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (window.Height > 0 && window.Width > 0)
|
||||
{
|
||||
rect.Height = -window.Y;
|
||||
rect.Height = -(int)(window.Y * item.Scale);
|
||||
|
||||
rect.Y += (int)(doorRect.Height * openState);
|
||||
rect.Height = Math.Max(rect.Height - (rect.Y - doorRect.Y), 0);
|
||||
@@ -52,12 +52,11 @@ namespace Barotrauma.Items.Components
|
||||
if (convexHull2 != null)
|
||||
{
|
||||
Rectangle rect2 = doorRect;
|
||||
rect2.Y = rect2.Y + window.Y - window.Height;
|
||||
rect2.Y = rect2.Y + (int)((window.Y * item.Scale - window.Height * item.Scale));
|
||||
|
||||
rect2.Y += (int)(doorRect.Height * openState);
|
||||
rect2.Y = Math.Min(doorRect.Y, rect2.Y);
|
||||
rect2.Height = rect2.Y - (doorRect.Y - (int)(doorRect.Height * (1.0f - openState)));
|
||||
//convexHull2.SetVertices(GetConvexHullCorners(rect2));
|
||||
|
||||
if (rect2.Height == 0)
|
||||
{
|
||||
@@ -86,7 +85,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing)
|
||||
{
|
||||
Color color = (item.IsSelected) ? Color.Green : Color.White;
|
||||
Color color = Color.White;
|
||||
if (brokenSprite == null)
|
||||
{
|
||||
//broken doors turn black if no broken sprite has been configured
|
||||
@@ -101,7 +100,7 @@ namespace Barotrauma.Items.Components
|
||||
weldSpritePos.Y = -weldSpritePos.Y;
|
||||
|
||||
weldedSprite.Draw(spriteBatch,
|
||||
weldSpritePos, Color.White * (stuck / 100.0f), 0.0f, 1.0f);
|
||||
weldSpritePos, Color.White * (stuck / 100.0f), scale: item.Scale);
|
||||
}
|
||||
|
||||
if (openState == 1.0f)
|
||||
@@ -122,7 +121,7 @@ namespace Barotrauma.Items.Components
|
||||
new Rectangle((int) (doorSprite.SourceRect.X + doorSprite.size.X * openState),
|
||||
(int) doorSprite.SourceRect.Y,
|
||||
(int) (doorSprite.size.X * (1.0f - openState)), (int) doorSprite.size.Y),
|
||||
color, 0.0f, doorSprite.Origin, 1.0f, SpriteEffects.None, doorSprite.Depth);
|
||||
color, 0.0f, doorSprite.Origin, item.Scale, SpriteEffects.None, doorSprite.Depth);
|
||||
}
|
||||
|
||||
if (brokenSprite != null && item.Health < item.Prefab.Health)
|
||||
@@ -132,7 +131,7 @@ namespace Barotrauma.Items.Components
|
||||
spriteBatch.Draw(brokenSprite.Texture, pos,
|
||||
new Rectangle((int)(brokenSprite.SourceRect.X + brokenSprite.size.X * openState), brokenSprite.SourceRect.Y,
|
||||
(int)(brokenSprite.size.X * (1.0f - openState)), (int)brokenSprite.size.Y),
|
||||
color * alpha, 0.0f, brokenSprite.Origin, scale, SpriteEffects.None,
|
||||
color * alpha, 0.0f, brokenSprite.Origin, scale * item.Scale, SpriteEffects.None,
|
||||
brokenSprite.Depth);
|
||||
}
|
||||
}
|
||||
@@ -148,7 +147,7 @@ namespace Barotrauma.Items.Components
|
||||
new Rectangle(doorSprite.SourceRect.X,
|
||||
(int) (doorSprite.SourceRect.Y + doorSprite.size.Y * openState),
|
||||
(int) doorSprite.size.X, (int) (doorSprite.size.Y * (1.0f - openState))),
|
||||
color, 0.0f, doorSprite.Origin, 1.0f, SpriteEffects.None, doorSprite.Depth);
|
||||
color, 0.0f, doorSprite.Origin, item.Scale, SpriteEffects.None, doorSprite.Depth);
|
||||
}
|
||||
|
||||
if (brokenSprite != null && item.Health < item.Prefab.Health)
|
||||
@@ -158,7 +157,7 @@ namespace Barotrauma.Items.Components
|
||||
spriteBatch.Draw(brokenSprite.Texture, pos,
|
||||
new Rectangle(brokenSprite.SourceRect.X, (int)(brokenSprite.SourceRect.Y + brokenSprite.size.Y * openState),
|
||||
(int)brokenSprite.size.X, (int)(brokenSprite.size.Y * (1.0f - openState))),
|
||||
color * alpha, 0.0f, brokenSprite.Origin, scale, SpriteEffects.None, brokenSprite.Depth);
|
||||
color * alpha, 0.0f, brokenSprite.Origin, scale * item.Scale, SpriteEffects.None, brokenSprite.Depth);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class ElectricalDischarger : Powered
|
||||
{
|
||||
private static SpriteSheet electricitySprite;
|
||||
|
||||
private int frameOffset;
|
||||
|
||||
partial void InitProjSpecific()
|
||||
{
|
||||
if (electricitySprite == null)
|
||||
{
|
||||
electricitySprite = new SpriteSheet("Content/Lights/Electricity.png", 4, 4, new Vector2(0.5f, 0.0f));
|
||||
}
|
||||
}
|
||||
|
||||
partial void DischargeProjSpecific()
|
||||
{
|
||||
PlaySound(ActionType.OnUse, item.WorldPosition);
|
||||
foreach (Node node in nodes)
|
||||
{
|
||||
GameMain.ParticleManager.CreateParticle("swirlysmoke", node.WorldPosition, Vector2.Zero);
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawElectricity(SpriteBatch spriteBatch)
|
||||
{
|
||||
for (int i = 0; i < nodes.Count; i++)
|
||||
{
|
||||
if (nodes[i].Length <= 1.0f) continue;
|
||||
var node = nodes[i];
|
||||
electricitySprite.Draw(spriteBatch,
|
||||
(i + frameOffset) % electricitySprite.FrameCount,
|
||||
new Vector2(node.WorldPosition.X, -node.WorldPosition.Y),
|
||||
Color.Lerp(Color.LightBlue, Color.White, Rand.Range(0.0f, 1.0f)),
|
||||
electricitySprite.Origin, -node.Angle - MathHelper.PiOver2,
|
||||
new Vector2(
|
||||
Math.Min(node.Length / electricitySprite.FrameSize.X, 1.0f) * Rand.Range(0.5f, 2.0f),
|
||||
node.Length / electricitySprite.FrameSize.Y) * Rand.Range(1.0f, 1.2f));
|
||||
}
|
||||
|
||||
if (GameMain.DebugDraw)
|
||||
{
|
||||
for (int i = 0; i < nodes.Count; i++)
|
||||
{
|
||||
if (nodes[i].Length <= 1.0f) continue;
|
||||
GUI.DrawRectangle(spriteBatch, new Vector2(nodes[i].WorldPosition.X, -nodes[i].WorldPosition.Y), Vector2.One * 5, Color.LightCyan, isFilled: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Barotrauma.Networking;
|
||||
using Barotrauma.Sounds;
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
@@ -10,25 +11,38 @@ using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
enum SoundSelectionMode
|
||||
{
|
||||
Random,
|
||||
CharacterSpecific,
|
||||
ItemSpecific,
|
||||
All
|
||||
}
|
||||
|
||||
class ItemSound
|
||||
{
|
||||
public readonly Sound Sound;
|
||||
public readonly RoundSound RoundSound;
|
||||
public readonly ActionType Type;
|
||||
|
||||
public string VolumeProperty;
|
||||
public float VolumeMultiplier
|
||||
{
|
||||
get { return RoundSound.Volume; }
|
||||
}
|
||||
|
||||
public float Range
|
||||
{
|
||||
get { return RoundSound.Range; }
|
||||
}
|
||||
|
||||
public float VolumeMultiplier;
|
||||
|
||||
public readonly float Range;
|
||||
|
||||
public readonly bool Loop;
|
||||
|
||||
public ItemSound(Sound sound, ActionType type, float range, bool loop = false)
|
||||
public ItemSound(RoundSound sound, ActionType type, bool loop = false)
|
||||
{
|
||||
this.Sound = sound;
|
||||
this.RoundSound = sound;
|
||||
this.Type = type;
|
||||
this.Range = range;
|
||||
|
||||
this.Loop = loop;
|
||||
}
|
||||
}
|
||||
@@ -36,71 +50,260 @@ namespace Barotrauma.Items.Components
|
||||
partial class ItemComponent : ISerializableEntity
|
||||
{
|
||||
private Dictionary<ActionType, List<ItemSound>> sounds;
|
||||
private Dictionary<ActionType, SoundSelectionMode> soundSelectionModes;
|
||||
|
||||
private GUIFrame guiFrame;
|
||||
public GUILayoutSettings DefaultLayout { get; protected set; }
|
||||
public GUILayoutSettings AlternativeLayout { get; protected set; }
|
||||
|
||||
protected GUIFrame GuiFrame
|
||||
public class GUILayoutSettings
|
||||
{
|
||||
get
|
||||
public Vector2? RelativeSize { get; private set; }
|
||||
public Point? AbsoluteSize { get; private set; }
|
||||
public Vector2? RelativeOffset { get; private set; }
|
||||
public Point? AbsoluteOffset { get; private set; }
|
||||
public Anchor? Anchor { get; private set; }
|
||||
public Pivot? Pivot { get; private set; }
|
||||
|
||||
public static GUILayoutSettings Load(XElement element)
|
||||
{
|
||||
if (guiFrame == null)
|
||||
var layout = new GUILayoutSettings();
|
||||
var relativeSize = XMLExtensions.GetAttributeVector2(element, "relativesize", Vector2.Zero);
|
||||
var absoluteSize = XMLExtensions.GetAttributePoint(element, "absolutesize", new Point(-1000, -1000));
|
||||
var relativeOffset = XMLExtensions.GetAttributeVector2(element, "relativeoffset", Vector2.Zero);
|
||||
var absoluteOffset = XMLExtensions.GetAttributePoint(element, "absoluteoffset", new Point(-1000, -1000));
|
||||
if (relativeSize.Length() > 0)
|
||||
{
|
||||
DebugConsole.ThrowError("Error: the component " + name + " in " + item.Name + " doesn't have a GuiFrame component");
|
||||
guiFrame = new GUIFrame(new Rectangle(0, 0, 100, 100), Color.Black);
|
||||
layout.RelativeSize = relativeSize;
|
||||
}
|
||||
return guiFrame;
|
||||
if (absoluteSize.X > 0 && absoluteSize.Y > 0)
|
||||
{
|
||||
layout.AbsoluteSize = absoluteSize;
|
||||
}
|
||||
if (relativeOffset.Length() > 0)
|
||||
{
|
||||
layout.RelativeOffset = relativeOffset;
|
||||
}
|
||||
if (absoluteOffset.X > -1000 && absoluteOffset.Y > -1000)
|
||||
{
|
||||
layout.AbsoluteOffset = absoluteOffset;
|
||||
}
|
||||
if (Enum.TryParse(XMLExtensions.GetAttributeString(element, "anchor", ""), out Anchor a))
|
||||
{
|
||||
layout.Anchor = a;
|
||||
}
|
||||
if (Enum.TryParse(XMLExtensions.GetAttributeString(element, "pivot", ""), out Pivot p))
|
||||
{
|
||||
layout.Pivot = p;
|
||||
}
|
||||
return layout;
|
||||
}
|
||||
|
||||
public void ApplyTo(RectTransform target)
|
||||
{
|
||||
if (RelativeOffset.HasValue)
|
||||
{
|
||||
target.RelativeOffset = RelativeOffset.Value;
|
||||
}
|
||||
else if (AbsoluteOffset.HasValue)
|
||||
{
|
||||
target.AbsoluteOffset = AbsoluteOffset.Value;
|
||||
}
|
||||
if (RelativeSize.HasValue)
|
||||
{
|
||||
target.RelativeSize = RelativeSize.Value;
|
||||
}
|
||||
else if (AbsoluteSize.HasValue)
|
||||
{
|
||||
target.NonScaledSize = AbsoluteSize.Value;
|
||||
}
|
||||
if (Anchor.HasValue)
|
||||
{
|
||||
target.Anchor = Anchor.Value;
|
||||
}
|
||||
if (Pivot.HasValue)
|
||||
{
|
||||
target.Pivot = Pivot.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
target.Pivot = RectTransform.MatchPivotToAnchor(target.Anchor);
|
||||
}
|
||||
target.RecalculateChildren(true, true);
|
||||
}
|
||||
}
|
||||
|
||||
public GUIFrame GuiFrame { get; protected set; }
|
||||
|
||||
[Serialize(false, false)]
|
||||
public bool AllowUIOverlap
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
private ItemComponent linkToUIComponent;
|
||||
[Serialize("", false)]
|
||||
public string LinkUIToComponent
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(0, false)]
|
||||
public int HudPriority
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
private bool useAlternativeLayout;
|
||||
public bool UseAlternativeLayout
|
||||
{
|
||||
get { return useAlternativeLayout; }
|
||||
set
|
||||
{
|
||||
if (AlternativeLayout != null)
|
||||
{
|
||||
if (value == useAlternativeLayout) { return; }
|
||||
useAlternativeLayout = value;
|
||||
if (useAlternativeLayout)
|
||||
{
|
||||
AlternativeLayout?.ApplyTo(GuiFrame.RectTransform);
|
||||
}
|
||||
else
|
||||
{
|
||||
DefaultLayout?.ApplyTo(GuiFrame.RectTransform);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool shouldMuffleLooping;
|
||||
private float lastMuffleCheckTime;
|
||||
private ItemSound loopingSound;
|
||||
private int loopingSoundIndex;
|
||||
public void PlaySound(ActionType type, Vector2 position)
|
||||
private SoundChannel loopingSoundChannel;
|
||||
public void PlaySound(ActionType type, Vector2 position, Character user = null)
|
||||
{
|
||||
if (loopingSound != null)
|
||||
{
|
||||
loopingSoundIndex = loopingSound.Sound.Loop(loopingSoundIndex, GetSoundVolume(loopingSound), position, loopingSound.Range);
|
||||
if (Vector3.DistanceSquared(GameMain.SoundManager.ListenerPosition, new Vector3(position.X, position.Y, 0.0f)) > loopingSound.Range * loopingSound.Range)
|
||||
{
|
||||
if (loopingSoundChannel != null)
|
||||
{
|
||||
loopingSoundChannel.Dispose(); loopingSoundChannel = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (loopingSoundChannel != null && loopingSoundChannel.Sound != loopingSound.RoundSound.Sound)
|
||||
{
|
||||
loopingSoundChannel.Dispose(); loopingSoundChannel = null;
|
||||
}
|
||||
if (loopingSoundChannel == null || !loopingSoundChannel.IsPlaying)
|
||||
{
|
||||
loopingSoundChannel = loopingSound.RoundSound.Sound.Play(
|
||||
new Vector3(position.X, position.Y, 0.0f),
|
||||
GetSoundVolume(loopingSound),
|
||||
SoundPlayer.ShouldMuffleSound(Character.Controlled, position, loopingSound.Range, Character.Controlled?.CurrentHull));
|
||||
loopingSoundChannel.Looping = true;
|
||||
//TODO: tweak
|
||||
loopingSoundChannel.Near = loopingSound.Range * 0.4f;
|
||||
loopingSoundChannel.Far = loopingSound.Range;
|
||||
}
|
||||
if (loopingSoundChannel != null)
|
||||
{
|
||||
if (Timing.TotalTime > lastMuffleCheckTime + 0.2f)
|
||||
{
|
||||
shouldMuffleLooping = SoundPlayer.ShouldMuffleSound(Character.Controlled, position, loopingSound.Range, Character.Controlled?.CurrentHull);
|
||||
lastMuffleCheckTime = (float)Timing.TotalTime;
|
||||
}
|
||||
loopingSoundChannel.Muffled = shouldMuffleLooping;
|
||||
loopingSoundChannel.Gain = GetSoundVolume(loopingSound);
|
||||
loopingSoundChannel.Position = new Vector3(position.X, position.Y, 0.0f);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
List<ItemSound> matchingSounds;
|
||||
if (!sounds.TryGetValue(type, out matchingSounds)) return;
|
||||
|
||||
if (!sounds.TryGetValue(type, out List<ItemSound> matchingSounds)) return;
|
||||
|
||||
ItemSound itemSound = null;
|
||||
if (!Sounds.SoundManager.IsPlaying(loopingSoundIndex))
|
||||
if (loopingSoundChannel == null || !loopingSoundChannel.IsPlaying)
|
||||
{
|
||||
int index = Rand.Int(matchingSounds.Count);
|
||||
SoundSelectionMode soundSelectionMode = soundSelectionModes[type];
|
||||
int index;
|
||||
if (soundSelectionMode == SoundSelectionMode.CharacterSpecific && user != null)
|
||||
{
|
||||
index = user.ID % matchingSounds.Count;
|
||||
}
|
||||
else if (soundSelectionMode == SoundSelectionMode.ItemSpecific)
|
||||
{
|
||||
index = item.ID % matchingSounds.Count;
|
||||
}
|
||||
else if (soundSelectionMode == SoundSelectionMode.All)
|
||||
{
|
||||
foreach (ItemSound sound in matchingSounds)
|
||||
{
|
||||
PlaySound(sound, position, user);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = Rand.Int(matchingSounds.Count);
|
||||
}
|
||||
|
||||
itemSound = matchingSounds[index];
|
||||
PlaySound(matchingSounds[index], position, user);
|
||||
}
|
||||
|
||||
if (itemSound == null) return;
|
||||
}
|
||||
|
||||
|
||||
private void PlaySound(ItemSound itemSound, Vector2 position, Character user = null)
|
||||
{
|
||||
if (Vector3.DistanceSquared(GameMain.SoundManager.ListenerPosition, new Vector3(position.X, position.Y, 0.0f)) > itemSound.Range * itemSound.Range)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (itemSound.Loop)
|
||||
{
|
||||
loopingSound = itemSound;
|
||||
|
||||
loopingSoundIndex = loopingSound.Sound.Loop(loopingSoundIndex, GetSoundVolume(loopingSound), position, loopingSound.Range);
|
||||
if (loopingSoundChannel != null && loopingSoundChannel.Sound != loopingSound.RoundSound.Sound)
|
||||
{
|
||||
loopingSoundChannel.Dispose(); loopingSoundChannel = null;
|
||||
}
|
||||
if (loopingSoundChannel == null || !loopingSoundChannel.IsPlaying)
|
||||
{
|
||||
loopingSoundChannel = loopingSound.RoundSound.Sound.Play(
|
||||
new Vector3(position.X, position.Y, 0.0f),
|
||||
GetSoundVolume(loopingSound),
|
||||
muffle: SoundPlayer.ShouldMuffleSound(Character.Controlled, position, loopingSound.Range, Character.Controlled?.CurrentHull));
|
||||
loopingSoundChannel.Looping = true;
|
||||
//TODO: tweak
|
||||
loopingSoundChannel.Near = loopingSound.Range * 0.4f;
|
||||
loopingSoundChannel.Far = loopingSound.Range;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float volume = GetSoundVolume(itemSound);
|
||||
if (volume == 0.0f) return;
|
||||
itemSound.Sound.Play(volume, itemSound.Range, position);
|
||||
if (volume <= 0.0f) return;
|
||||
SoundPlayer.PlaySound(itemSound.RoundSound.Sound, volume, itemSound.Range, position, item.CurrentHull);
|
||||
}
|
||||
}
|
||||
|
||||
public void StopSounds(ActionType type)
|
||||
{
|
||||
if (loopingSoundIndex <= 0) return;
|
||||
|
||||
if (loopingSound == null) return;
|
||||
|
||||
if (loopingSound.Type != type) return;
|
||||
|
||||
if (Sounds.SoundManager.IsPlaying(loopingSoundIndex))
|
||||
if (loopingSoundChannel != null)
|
||||
{
|
||||
Sounds.SoundManager.Stop(loopingSoundIndex);
|
||||
loopingSoundChannel.Dispose();
|
||||
loopingSoundChannel = null;
|
||||
loopingSound = null;
|
||||
loopingSoundIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,8 +312,7 @@ namespace Barotrauma.Items.Components
|
||||
if (sound == null) return 0.0f;
|
||||
if (sound.VolumeProperty == "") return 1.0f;
|
||||
|
||||
SerializableProperty property = null;
|
||||
if (properties.TryGetValue(sound.VolumeProperty.ToLowerInvariant(), out property))
|
||||
if (properties.TryGetValue(sound.VolumeProperty.ToLowerInvariant(), out SerializableProperty property))
|
||||
{
|
||||
float newVolume = 0.0f;
|
||||
try
|
||||
@@ -123,55 +325,80 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
newVolume *= sound.VolumeMultiplier;
|
||||
|
||||
if (!MathUtils.IsValid(newVolume))
|
||||
{
|
||||
DebugConsole.Log("Invalid sound volume (item " + item.Name + ", " + GetType().ToString() + "): " + newVolume);
|
||||
GameAnalyticsManager.AddErrorEventOnce(
|
||||
"ItemComponent.PlaySound:" + item.Name + GetType().ToString(),
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
"Invalid sound volume (item " + item.Name + ", " + GetType().ToString() + "): " + newVolume);
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return MathHelper.Clamp(newVolume, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
public virtual bool ShouldDrawHUD(Character character)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public ItemComponent GetLinkUIToComponent()
|
||||
{
|
||||
if (string.IsNullOrEmpty(LinkUIToComponent))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
foreach (ItemComponent component in item.components)
|
||||
{
|
||||
if (component.name.ToLower() == LinkUIToComponent.ToLower())
|
||||
{
|
||||
linkToUIComponent = component;
|
||||
}
|
||||
}
|
||||
if (linkToUIComponent == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to link the component \"" + Name + "\" to \"" + LinkUIToComponent + "\" in the item \"" + item.Name + "\" - component with a matching name not found.");
|
||||
}
|
||||
return linkToUIComponent;
|
||||
}
|
||||
|
||||
public virtual void DrawHUD(SpriteBatch spriteBatch, Character character) { }
|
||||
|
||||
public virtual void AddToGUIUpdateList() { }
|
||||
public virtual void AddToGUIUpdateList()
|
||||
{
|
||||
GuiFrame?.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
public virtual void UpdateHUD(Character character) { }
|
||||
public virtual void UpdateHUD(Character character, float deltaTime, Camera cam) { }
|
||||
|
||||
private bool LoadElemProjSpecific(XElement subElement)
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "guiframe":
|
||||
string rectStr = subElement.GetAttributeString("rect", "0.0,0.0,0.5,0.5");
|
||||
|
||||
string[] components = rectStr.Split(',');
|
||||
if (components.Length < 4) break;
|
||||
|
||||
Vector4 rect = subElement.GetAttributeVector4("rect", Vector4.One);
|
||||
if (components[0].Contains(".")) rect.X *= GameMain.GraphicsWidth;
|
||||
if (components[1].Contains(".")) rect.Y *= GameMain.GraphicsHeight;
|
||||
if (components[2].Contains(".")) rect.Z *= GameMain.GraphicsWidth;
|
||||
if (components[3].Contains(".")) rect.W *= GameMain.GraphicsHeight;
|
||||
|
||||
string style = subElement.GetAttributeString("style", "");
|
||||
|
||||
Vector4 color = subElement.GetAttributeVector4("color", Vector4.One);
|
||||
|
||||
Alignment alignment = Alignment.Center;
|
||||
try
|
||||
if (subElement.Attribute("rect") != null)
|
||||
{
|
||||
alignment = (Alignment)Enum.Parse(typeof(Alignment),
|
||||
subElement.GetAttributeString("alignment", "Center"), true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
DebugConsole.ThrowError("Error in " + subElement.Parent + "! \"" + subElement.Parent.Attribute("type").Value + "\" is not a valid alignment");
|
||||
DebugConsole.ThrowError("Error in item config \"" + item.ConfigFile + "\" - GUIFrame defined as rect, use RectTransform instead.");
|
||||
break;
|
||||
}
|
||||
|
||||
guiFrame = new GUIFrame(
|
||||
new Rectangle((int)rect.X, (int)rect.Y, (int)rect.Z, (int)rect.W),
|
||||
new Color(color.X, color.Y, color.Z) * color.W,
|
||||
alignment, style);
|
||||
Color? color = null;
|
||||
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), style, color);
|
||||
DefaultLayout = GUILayoutSettings.Load(subElement);
|
||||
break;
|
||||
case "alternativelayout":
|
||||
AlternativeLayout = GUILayoutSettings.Load(subElement);
|
||||
break;
|
||||
case "itemsound":
|
||||
case "sound":
|
||||
string filePath = subElement.GetAttributeString("file", "");
|
||||
|
||||
@@ -189,7 +416,6 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
ActionType type;
|
||||
|
||||
try
|
||||
{
|
||||
type = (ActionType)Enum.Parse(typeof(ActionType), subElement.GetAttributeString("type", ""), true);
|
||||
@@ -199,14 +425,20 @@ namespace Barotrauma.Items.Components
|
||||
DebugConsole.ThrowError("Invalid sound type in " + subElement + "!", e);
|
||||
break;
|
||||
}
|
||||
|
||||
RoundSound sound = Submarine.LoadRoundSound(subElement);
|
||||
ItemSound itemSound = new ItemSound(sound, type, subElement.GetAttributeBool("loop", false))
|
||||
{
|
||||
VolumeProperty = subElement.GetAttributeString("volumeproperty", "")
|
||||
};
|
||||
|
||||
Sound sound = Sound.Load(filePath);
|
||||
|
||||
float range = subElement.GetAttributeFloat("range", 800.0f);
|
||||
bool loop = subElement.GetAttributeBool("loop", false);
|
||||
ItemSound itemSound = new ItemSound(sound, type, range, loop);
|
||||
itemSound.VolumeProperty = subElement.GetAttributeString("volume", "");
|
||||
itemSound.VolumeMultiplier = subElement.GetAttributeFloat("volumemultiplier", 1.0f);
|
||||
if (soundSelectionModes == null) soundSelectionModes = new Dictionary<ActionType, SoundSelectionMode>();
|
||||
if (!soundSelectionModes.ContainsKey(type) || soundSelectionModes[type] == SoundSelectionMode.Random)
|
||||
{
|
||||
SoundSelectionMode selectionMode = SoundSelectionMode.Random;
|
||||
Enum.TryParse(subElement.GetAttributeString("selectionmode", "Random"), out selectionMode);
|
||||
soundSelectionModes[type] = selectionMode;
|
||||
}
|
||||
|
||||
List<ItemSound> soundList = null;
|
||||
if (!sounds.TryGetValue(itemSound.Type, out soundList))
|
||||
|
||||
@@ -1,29 +1,146 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class ItemContainer : ItemComponent, IDrawableComponent
|
||||
{
|
||||
//TODO: shouldn't this be overriding the base method?
|
||||
private Sprite inventoryTopSprite;
|
||||
private Sprite inventoryBackSprite;
|
||||
private Sprite inventoryBottomSprite;
|
||||
|
||||
private GUICustomComponent guiCustomComponent;
|
||||
|
||||
public Sprite InventoryTopSprite
|
||||
{
|
||||
get { return inventoryTopSprite; }
|
||||
}
|
||||
public Sprite InventoryBackSprite
|
||||
{
|
||||
get { return inventoryBackSprite; }
|
||||
}
|
||||
public Sprite InventoryBottomSprite
|
||||
{
|
||||
get { return inventoryBottomSprite; }
|
||||
}
|
||||
|
||||
public Sprite ContainedStateIndicator
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
[Serialize("0.0,0.0", false), Editable]
|
||||
#else
|
||||
[Serialize("0.0,0.0", false)]
|
||||
#endif
|
||||
public Vector2 ItemPos { get; set; }
|
||||
|
||||
#if DEBUG
|
||||
[Serialize("0.0,0.0", false), Editable]
|
||||
#else
|
||||
[Serialize("0.0,0.0", false)]
|
||||
#endif
|
||||
public Vector2 ItemInterval { get; set; }
|
||||
[Serialize(100, false)]
|
||||
public int ItemsPerRow { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Depth at which the contained sprites are drawn. If not set, the original depth of the item sprites is used.
|
||||
/// </summary>
|
||||
[Serialize(-1.0f, false)]
|
||||
public float ContainedSpriteDepth { get; set; }
|
||||
|
||||
|
||||
private float itemRotation;
|
||||
[Serialize(0.0f, false)]
|
||||
public float ItemRotation
|
||||
{
|
||||
get { return MathHelper.ToDegrees(itemRotation); }
|
||||
set { itemRotation = MathHelper.ToRadians(value); }
|
||||
}
|
||||
|
||||
[Serialize(null, false)]
|
||||
public string UILabel { get; set; }
|
||||
|
||||
[Serialize(false, false)]
|
||||
public bool ShowConditionInContainedStateIndicator
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
partial void InitProjSpecific(XElement element)
|
||||
{
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "topsprite":
|
||||
inventoryTopSprite = new Sprite(subElement);
|
||||
break;
|
||||
case "backsprite":
|
||||
inventoryBackSprite = new Sprite(subElement);
|
||||
break;
|
||||
case "bottomsprite":
|
||||
inventoryBottomSprite = new Sprite(subElement);
|
||||
break;
|
||||
case "containedstateindicator":
|
||||
ContainedStateIndicator = new Sprite(subElement);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (GuiFrame == null)
|
||||
{
|
||||
//if a GUIFrame is not defined in the xml,
|
||||
//we create a full-screen frame and let the inventory position itself on it
|
||||
GuiFrame = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas), style: null)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
guiCustomComponent = new GUICustomComponent(new RectTransform(Vector2.One, GuiFrame.RectTransform),
|
||||
onDraw: (SpriteBatch spriteBatch, GUICustomComponent component) => { Inventory.Draw(spriteBatch); },
|
||||
onUpdate: null)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
//if a GUIFrame has been defined, draw the inventory inside it
|
||||
guiCustomComponent = new GUICustomComponent(new RectTransform(new Vector2(0.9f), GuiFrame.RectTransform, Anchor.Center),
|
||||
onDraw: (SpriteBatch spriteBatch, GUICustomComponent component) => { Inventory.Draw(spriteBatch); },
|
||||
onUpdate: null)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
Inventory.RectTransform = guiCustomComponent.RectTransform;
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing = false)
|
||||
{
|
||||
if (hideItems || (item.body != null && !item.body.Enabled)) return;
|
||||
if (hideItems || (item.body != null && !item.body.Enabled)) { return; }
|
||||
DrawContainedItems(spriteBatch);
|
||||
}
|
||||
|
||||
Vector2 transformedItemPos = itemPos;
|
||||
Vector2 transformedItemInterval = itemInterval;
|
||||
public void DrawContainedItems(SpriteBatch spriteBatch)
|
||||
{
|
||||
Vector2 transformedItemPos = ItemPos * item.Scale;
|
||||
Vector2 transformedItemInterval = ItemInterval * item.Scale;
|
||||
float currentRotation = itemRotation;
|
||||
|
||||
if (item.body == null)
|
||||
{
|
||||
transformedItemPos = new Vector2(item.Rect.X, item.Rect.Y);
|
||||
if (item.Submarine != null) transformedItemPos += item.Submarine.DrawPosition;
|
||||
transformedItemPos = transformedItemPos + itemPos;
|
||||
transformedItemPos = transformedItemPos + ItemPos * item.Scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
//item.body.Enabled = true;
|
||||
|
||||
Matrix transform = Matrix.CreateRotationZ(item.body.Rotation);
|
||||
|
||||
if (item.body.Dir == -1.0f)
|
||||
@@ -39,30 +156,80 @@ namespace Barotrauma.Items.Components
|
||||
currentRotation += item.body.Rotation;
|
||||
}
|
||||
|
||||
Vector2 currentItemPos = transformedItemPos;
|
||||
|
||||
int i = 0;
|
||||
foreach (Item containedItem in Inventory.Items)
|
||||
{
|
||||
if (containedItem == null) continue;
|
||||
|
||||
if (AutoInteractWithContained)
|
||||
{
|
||||
containedItem.IsHighlighted = item.IsHighlighted;
|
||||
item.IsHighlighted = false;
|
||||
}
|
||||
|
||||
if (containedItem.body != null)
|
||||
{
|
||||
containedItem.body.FarseerBody.Rotation = currentRotation;
|
||||
}
|
||||
|
||||
containedItem.Sprite.Draw(
|
||||
spriteBatch,
|
||||
new Vector2(transformedItemPos.X, -transformedItemPos.Y),
|
||||
new Vector2(currentItemPos.X, -currentItemPos.Y),
|
||||
containedItem.GetSpriteColor(),
|
||||
-currentRotation,
|
||||
1.0f,
|
||||
(item.body != null && item.body.Dir == -1) ? SpriteEffects.FlipHorizontally : SpriteEffects.None);
|
||||
containedItem.Scale,
|
||||
(item.body != null && item.body.Dir == -1) ? SpriteEffects.FlipHorizontally : SpriteEffects.None,
|
||||
depth: ContainedSpriteDepth < 0.0f ? containedItem.Sprite.Depth : ContainedSpriteDepth);
|
||||
|
||||
transformedItemPos += transformedItemInterval;
|
||||
foreach (ItemContainer ic in containedItem.GetComponents<ItemContainer>())
|
||||
{
|
||||
if (ic.hideItems) continue;
|
||||
ic.DrawContainedItems(spriteBatch);
|
||||
}
|
||||
|
||||
i++;
|
||||
if (Math.Abs(transformedItemInterval.X) > 0.001f && Math.Abs(transformedItemInterval.Y) > 0.001f)
|
||||
{
|
||||
//interval set on both axes -> use a grid layout
|
||||
currentItemPos.X += transformedItemInterval.X;
|
||||
if (i % ItemsPerRow == 0)
|
||||
{
|
||||
currentItemPos.X = transformedItemPos.X;
|
||||
currentItemPos.Y += transformedItemInterval.Y;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
currentItemPos += transformedItemInterval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateHUD(Character character)
|
||||
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
||||
{
|
||||
Inventory.Update((float)Timing.Step);
|
||||
if (Inventory.RectTransform != null)
|
||||
{
|
||||
guiCustomComponent.RectTransform.Parent = Inventory.RectTransform;
|
||||
}
|
||||
|
||||
//if the item is in the character's inventory, no need to update the item's inventory
|
||||
//because the player can see it by hovering the cursor over the item
|
||||
guiCustomComponent.Visible = item.ParentInventory?.Owner != character && DrawInventory;
|
||||
if (!guiCustomComponent.Visible) return;
|
||||
|
||||
Inventory.Update(deltaTime, cam);
|
||||
}
|
||||
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
/*public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
{
|
||||
Inventory.Draw(spriteBatch);
|
||||
}
|
||||
//if the item is in the character's inventory, no need to draw the item's inventory
|
||||
//because the player can see it by hovering the cursor over the item
|
||||
if (item.ParentInventory?.Owner == character || !DrawInventory) return;
|
||||
|
||||
Inventory.Draw(spriteBatch);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
@@ -10,20 +12,38 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private Color textColor;
|
||||
|
||||
private float scrollAmount;
|
||||
private string scrollingText;
|
||||
private float scrollPadding;
|
||||
private int scrollIndex;
|
||||
private bool needsScrolling;
|
||||
|
||||
private float[] charWidths;
|
||||
|
||||
[Serialize("0,0,0,0", true)]
|
||||
public Vector4 Padding
|
||||
{
|
||||
get { return TextBlock.Padding; }
|
||||
set { TextBlock.Padding = value; }
|
||||
}
|
||||
|
||||
private string text;
|
||||
[Serialize("", true), Editable(100)]
|
||||
public string Text
|
||||
{
|
||||
get { return textBlock.Text.Replace("\n", ""); }
|
||||
get { return text; }
|
||||
set
|
||||
{
|
||||
if (value == TextBlock.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)
|
||||
{
|
||||
textBlock = null;
|
||||
}
|
||||
|
||||
text = value;
|
||||
TextBlock.Text = value;
|
||||
SetScrollingText();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,42 +68,149 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
private bool scrollable;
|
||||
[Serialize(false, true)]
|
||||
public bool Scrollable
|
||||
{
|
||||
get { return scrollable; }
|
||||
set
|
||||
{
|
||||
scrollable = value;
|
||||
IsActive = value;
|
||||
TextBlock.Wrap = !scrollable;
|
||||
TextBlock.TextAlignment = scrollable ? Alignment.CenterLeft : Alignment.Center;
|
||||
}
|
||||
}
|
||||
|
||||
[Serialize(20.0f, true)]
|
||||
public float ScrollSpeed
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
private GUITextBlock TextBlock
|
||||
{
|
||||
get
|
||||
{
|
||||
if (textBlock == null)
|
||||
{
|
||||
textBlock = new GUITextBlock(new Rectangle(item.Rect.X, -item.Rect.Y, item.Rect.Width, item.Rect.Height), "",
|
||||
Color.Transparent, textColor,
|
||||
Alignment.TopLeft, Alignment.Center,
|
||||
null, null, true);
|
||||
textBlock.Font = GUI.SmallFont;
|
||||
textBlock.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f);
|
||||
textBlock.TextDepth = item.Sprite.Depth - 0.0001f;
|
||||
textBlock.TextScale = TextScale;
|
||||
textBlock = new GUITextBlock(new RectTransform(item.Rect.Size), "",
|
||||
textColor: textColor, font: GUI.SmallFont, textAlignment: Alignment.Center, wrap: true, style: null)
|
||||
{
|
||||
TextDepth = item.SpriteDepth - 0.0001f,
|
||||
TextScale = TextScale
|
||||
};
|
||||
}
|
||||
return textBlock;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Move(Vector2 amount)
|
||||
{
|
||||
textBlock.Rect = new Rectangle(item.Rect.X, -item.Rect.Y, item.Rect.Width, item.Rect.Height);
|
||||
}
|
||||
|
||||
public ItemLabel(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
{
|
||||
}
|
||||
|
||||
private void SetScrollingText()
|
||||
{
|
||||
if (!scrollable) return;
|
||||
|
||||
float totalWidth = textBlock.Font.MeasureString(text).X;
|
||||
float textAreaWidth = Math.Max(textBlock.Rect.Width - textBlock.Padding.X - textBlock.Padding.Z, 0);
|
||||
if (totalWidth >= textAreaWidth)
|
||||
{
|
||||
//add enough spaces to fill the rect
|
||||
//(so the text can scroll entirely out of view before we reset it back to start)
|
||||
needsScrolling = true;
|
||||
float spaceWidth = textBlock.Font.MeasureChar(' ').X;
|
||||
scrollingText = new string(' ', (int)Math.Ceiling(textAreaWidth / spaceWidth)) + text;
|
||||
}
|
||||
else
|
||||
{
|
||||
//whole text can fit in the textblock, no need to scroll
|
||||
needsScrolling = false;
|
||||
scrollingText = text;
|
||||
scrollAmount = 0.0f;
|
||||
scrollIndex = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
//calculate character widths
|
||||
scrollPadding = 0;
|
||||
charWidths = new float[scrollingText.Length];
|
||||
for (int i = 0; i < scrollingText.Length; i++)
|
||||
{
|
||||
float charWidth = TextBlock.Font.MeasureChar(scrollingText[i]).X;
|
||||
scrollPadding = Math.Max(charWidth, scrollPadding);
|
||||
charWidths[i] = charWidth;
|
||||
}
|
||||
|
||||
scrollIndex = MathHelper.Clamp(scrollIndex, 0, text.Length);
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
if (!scrollable) return;
|
||||
|
||||
if (scrollingText == null)
|
||||
{
|
||||
SetScrollingText();
|
||||
}
|
||||
|
||||
if (!needsScrolling) return;
|
||||
|
||||
scrollAmount -= deltaTime * ScrollSpeed;
|
||||
|
||||
float currLength = 0;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
float textAreaWidth = textBlock.Rect.Width - textBlock.Padding.X - textBlock.Padding.Z;
|
||||
for (int i = scrollIndex; i < scrollingText.Length; i++)
|
||||
{
|
||||
//first character is out of view -> skip to next character
|
||||
if (i == scrollIndex && scrollAmount < -charWidths[i])
|
||||
{
|
||||
scrollIndex++;
|
||||
scrollAmount = 0;
|
||||
if (scrollIndex >= scrollingText.Length) //reached the last character, reset
|
||||
{
|
||||
scrollIndex = 0;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
//reached the right edge, stop adding more character
|
||||
if (scrollAmount + (currLength + charWidths[i] + scrollPadding) >= textAreaWidth)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
currLength += charWidths[i];
|
||||
sb.Append(scrollingText[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TextBlock.Text = sb.ToString();
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing = false)
|
||||
{
|
||||
var drawPos = new Vector2(
|
||||
item.DrawPosition.X - item.Rect.Width / 2.0f,
|
||||
-(item.DrawPosition.Y + item.Rect.Height / 2.0f));
|
||||
|
||||
Rectangle worldRect = item.WorldRect;
|
||||
if (worldRect.X > Screen.Selected.Cam.WorldView.Right ||
|
||||
worldRect.Right < Screen.Selected.Cam.WorldView.X ||
|
||||
worldRect.Y < Screen.Selected.Cam.WorldView.Y - Screen.Selected.Cam.WorldView.Height ||
|
||||
worldRect.Y - worldRect.Height > Screen.Selected.Cam.WorldView.Y)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
textBlock.Draw(spriteBatch, drawPos - textBlock.Rect.Location.ToVector2());
|
||||
textBlock.TextOffset = drawPos - textBlock.Rect.Location.ToVector2() + new Vector2(scrollAmount + scrollPadding, 0.0f);
|
||||
textBlock.DrawManually(spriteBatch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
using Barotrauma.Networking;
|
||||
using Lidgren.Network;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class LevelResource : ItemComponent, IServerSerializable
|
||||
{
|
||||
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
|
||||
{
|
||||
DeattachTimer = msg.ReadSingle();
|
||||
if (deattachTimer >= DeattachDuration)
|
||||
{
|
||||
holdable.DeattachFromWall();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,16 +9,20 @@ namespace Barotrauma.Items.Components
|
||||
partial class LightComponent : Powered, IServerSerializable, IDrawableComponent
|
||||
{
|
||||
private LightSource light;
|
||||
|
||||
public LightSource Light
|
||||
{
|
||||
get { return light; }
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing = false)
|
||||
{
|
||||
if (light.LightSprite != null && (item.body == null || item.body.Enabled))
|
||||
if (light.LightSprite != null && (item.body == null || item.body.Enabled) && lightBrightness > 0.0f)
|
||||
{
|
||||
light.LightSprite.Draw(spriteBatch, new Vector2(item.DrawPosition.X, -item.DrawPosition.Y), lightColor * lightBrightness, 0.0f, 1.0f, Microsoft.Xna.Framework.Graphics.SpriteEffects.None, item.Sprite.Depth - 0.0001f);
|
||||
light.LightSprite.Draw(spriteBatch, new Vector2(item.DrawPosition.X, -item.DrawPosition.Y), lightColor * lightBrightness, 0.0f, 1.0f, Microsoft.Xna.Framework.Graphics.SpriteEffects.None, item.SpriteDepth - 0.0001f);
|
||||
}
|
||||
}
|
||||
|
||||
public override void FlipX()
|
||||
public override void FlipX(bool relativeToSub)
|
||||
{
|
||||
if (light?.LightSprite != null)
|
||||
{
|
||||
|
||||
@@ -1,27 +1,77 @@
|
||||
using Barotrauma.Networking;
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class Deconstructor : Powered, IServerSerializable, IClientSerializable
|
||||
{
|
||||
GUIProgressBar progressBar;
|
||||
GUIButton activateButton;
|
||||
private GUIButton activateButton;
|
||||
private GUIComponent inputInventoryHolder, outputInventoryHolder;
|
||||
private GUICustomComponent inputInventoryOverlay;
|
||||
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
private GUIComponent inSufficientPowerWarning;
|
||||
|
||||
partial void InitProjSpecific(XElement element)
|
||||
{
|
||||
GuiFrame.Draw(spriteBatch);
|
||||
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
|
||||
inputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(0.2f, 0.7f), paddedFrame.RectTransform), style: null);
|
||||
inputInventoryOverlay = new GUICustomComponent(new RectTransform(Vector2.One, inputInventoryHolder.RectTransform), DrawOverLay, null)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
activateButton = new GUIButton(new RectTransform(new Vector2(0.8f, 0.1f), paddedFrame.RectTransform),
|
||||
TextManager.Get("DeconstructorDeconstruct"))
|
||||
{
|
||||
OnClicked = ToggleActive
|
||||
};
|
||||
|
||||
|
||||
inSufficientPowerWarning = new GUITextBlock(new RectTransform(Vector2.One, activateButton.RectTransform), TextManager.Get("DeconstructorNoPower"),
|
||||
textColor: Color.Orange, textAlignment: Alignment.Center, color: Color.Black, style: "OuterGlow")
|
||||
{
|
||||
HoverColor = Color.Black,
|
||||
IgnoreLayoutGroups = true,
|
||||
Visible = false,
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
outputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.3f), paddedFrame.RectTransform), style: null);
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
partial void OnItemLoadedProjSpecific()
|
||||
{
|
||||
GuiFrame.AddToGUIUpdateList();
|
||||
inputContainer.AllowUIOverlap = true;
|
||||
inputContainer.Inventory.RectTransform = inputInventoryHolder.RectTransform;
|
||||
outputContainer.AllowUIOverlap = true;
|
||||
outputContainer.Inventory.RectTransform = outputInventoryHolder.RectTransform;
|
||||
}
|
||||
|
||||
public override void UpdateHUD(Character character)
|
||||
private void DrawOverLay(SpriteBatch spriteBatch, GUICustomComponent overlayComponent)
|
||||
{
|
||||
GuiFrame.Update((float)Timing.Step);
|
||||
overlayComponent.RectTransform.SetAsLastChild();
|
||||
var lastSlot = inputContainer.Inventory.slots.Last();
|
||||
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
new Rectangle(
|
||||
lastSlot.Rect.X, lastSlot.Rect.Y + (int)(lastSlot.Rect.Height * (1.0f - progressState)),
|
||||
lastSlot.Rect.Width, (int)(lastSlot.Rect.Height * progressState)),
|
||||
Color.Green * 0.5f, isFilled: true);
|
||||
}
|
||||
|
||||
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
||||
{
|
||||
inSufficientPowerWarning.Visible = powerConsumption > 0 && voltage < minVoltage;
|
||||
activateButton.Enabled = !inSufficientPowerWarning.Visible;
|
||||
}
|
||||
|
||||
private bool ToggleActive(GUIButton button, object obj)
|
||||
|
||||
@@ -1,25 +1,142 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Barotrauma.Networking;
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class Engine : Powered
|
||||
partial class Engine : Powered, IDrawableComponent
|
||||
{
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
{
|
||||
GuiFrame.Draw(spriteBatch);
|
||||
private float spriteIndex;
|
||||
|
||||
GUI.Font.DrawString(spriteBatch, TextManager.Get("Force") + ": " + (int)(targetForce) + " %", new Vector2(GuiFrame.Rect.X + 30, GuiFrame.Rect.Y + 30), Color.White);
|
||||
private SpriteSheet propellerSprite;
|
||||
|
||||
private GUITickBox powerIndicator;
|
||||
private GUIScrollBar forceSlider;
|
||||
|
||||
public float AnimSpeed
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
partial void InitProjSpecific(XElement element)
|
||||
{
|
||||
GuiFrame.AddToGUIUpdateList();
|
||||
powerIndicator = new GUITickBox(new RectTransform(new Point(30, 30), GuiFrame.RectTransform) { RelativeOffset = new Vector2(0.05f, 0.15f) },
|
||||
TextManager.Get("EnginePowered"), style: "IndicatorLightGreen")
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
string powerLabel = TextManager.Get("EngineForce");
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.9f, 0.3f), GuiFrame.RectTransform, Anchor.BottomCenter)
|
||||
{ RelativeOffset = new Vector2(0.0f, 0.4f) }, "", textAlignment: Alignment.Center)
|
||||
{
|
||||
TextGetter = () => { return powerLabel + ": " + (int)(targetForce) + " %"; }
|
||||
};
|
||||
|
||||
var sliderArea = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.25f), GuiFrame.RectTransform, Anchor.BottomCenter)
|
||||
{ RelativeOffset = new Vector2(0.0f, 0.2f) }, isHorizontal: true);
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.2f, 1.0f), sliderArea.RectTransform), TextManager.Get("EngineBackwards"),
|
||||
font: GUI.SmallFont, textAlignment: Alignment.Center);
|
||||
forceSlider = new GUIScrollBar(new RectTransform(new Vector2(0.6f, 1.0f), sliderArea.RectTransform), barSize: 0.25f, style: "GUISlider")
|
||||
{
|
||||
Step = 0.05f,
|
||||
OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
|
||||
{
|
||||
float newTargetForce = barScroll * 200.0f - 100.0f;
|
||||
if (Math.Abs(newTargetForce - targetForce) < 0.01) return false;
|
||||
|
||||
targetForce = newTargetForce;
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
GameServer.Log(Character.Controlled.LogName + " set the force speed of " + item.Name + " to " + (int)(targetForce) + " %", ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
else if (GameMain.Client != null)
|
||||
{
|
||||
correctionTimer = CorrectionDelay;
|
||||
item.CreateClientEvent(this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.2f, 1.0f), sliderArea.RectTransform), TextManager.Get("EngineForwards"),
|
||||
font: GUI.SmallFont, textAlignment: Alignment.Center);
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "propellersprite":
|
||||
propellerSprite = new SpriteSheet(subElement);
|
||||
AnimSpeed = subElement.GetAttributeFloat("animspeed", 1.0f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateHUD(Character character)
|
||||
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
||||
{
|
||||
GuiFrame.Update(1.0f / 60.0f);
|
||||
powerIndicator.Selected = hasPower && IsActive;
|
||||
|
||||
if (!PlayerInput.LeftButtonHeld())
|
||||
{
|
||||
float newScroll = (targetForce + 100.0f) / 200.0f;
|
||||
if (Math.Abs(newScroll - forceSlider.BarScroll) > 0.01f)
|
||||
{
|
||||
forceSlider.BarScroll = newScroll;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
partial void UpdateAnimation(float deltaTime)
|
||||
{
|
||||
if (propellerSprite == null) return;
|
||||
|
||||
spriteIndex += (force / 100.0f) * AnimSpeed * deltaTime;
|
||||
if (spriteIndex < 0) spriteIndex = propellerSprite.FrameCount;
|
||||
if (spriteIndex >= propellerSprite.FrameCount) spriteIndex = 0.0f;
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing)
|
||||
{
|
||||
if (propellerSprite != null)
|
||||
{
|
||||
Vector2 drawPos = item.DrawPosition;
|
||||
drawPos += PropellerPos;
|
||||
drawPos.Y = -drawPos.Y;
|
||||
|
||||
propellerSprite.Draw(spriteBatch, (int)Math.Floor(spriteIndex), drawPos, Color.White, propellerSprite.Origin, 0.0f, Vector2.One);
|
||||
}
|
||||
|
||||
if (editing)
|
||||
{
|
||||
Vector2 drawPos = item.DrawPosition;
|
||||
drawPos += PropellerPos;
|
||||
drawPos.Y = -drawPos.Y;
|
||||
GUI.DrawRectangle(spriteBatch, drawPos - Vector2.One * 10, Vector2.One * 20, Color.Red);
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientWrite(NetBuffer msg, object[] extraData = null)
|
||||
{
|
||||
//targetForce can only be adjusted at 10% intervals -> no need for more accuracy than this
|
||||
msg.WriteRangedInteger(-10, 10, (int)(targetForce / 10.0f));
|
||||
}
|
||||
|
||||
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
|
||||
{
|
||||
if (correctionTimer > 0.0f)
|
||||
{
|
||||
StartDelayedCorrection(type, msg.ExtractBits(5), sendingTime);
|
||||
return;
|
||||
}
|
||||
|
||||
targetForce = msg.ReadRangedInteger(-10, 10) * 10.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Barotrauma.Networking;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Networking;
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
@@ -13,148 +14,309 @@ namespace Barotrauma.Items.Components
|
||||
private GUIListBox itemList;
|
||||
|
||||
private GUIFrame selectedItemFrame;
|
||||
|
||||
private GUIProgressBar progressBar;
|
||||
|
||||
private GUIButton activateButton;
|
||||
|
||||
private GUIComponent inputInventoryHolder, outputInventoryHolder;
|
||||
private GUICustomComponent inputInventoryOverlay, outputInventoryOverlay;
|
||||
|
||||
private FabricableItem selectedItem;
|
||||
|
||||
private GUIComponent inSufficientPowerWarning;
|
||||
|
||||
private Pair<Rectangle, string> tooltip;
|
||||
|
||||
partial void InitProjSpecific()
|
||||
{
|
||||
GuiFrame.Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f);
|
||||
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
|
||||
itemList = new GUIListBox(new Rectangle(0, 0, GuiFrame.Rect.Width / 2 - 20, 0), "", GuiFrame);
|
||||
itemList.OnSelected = SelectItem;
|
||||
itemList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.5f), paddedFrame.RectTransform))
|
||||
{
|
||||
OnSelected = SelectItem
|
||||
};
|
||||
|
||||
inputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(0.7f, 0.15f), paddedFrame.RectTransform), style: null);
|
||||
inputInventoryOverlay = new GUICustomComponent(new RectTransform(Vector2.One, inputInventoryHolder.RectTransform), DrawInputOverLay, null)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
var outputArea = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.3f), paddedFrame.RectTransform), isHorizontal: true);
|
||||
|
||||
selectedItemFrame = new GUIFrame(new RectTransform(new Vector2(0.75f, 1.0f), outputArea.RectTransform), style: "InnerFrame");
|
||||
outputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(0.25f, 1.0f), outputArea.RectTransform), style: null);
|
||||
outputInventoryOverlay = new GUICustomComponent(new RectTransform(Vector2.One, outputArea.RectTransform), DrawOutputOverLay, null)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
foreach (FabricableItem fi in fabricableItems)
|
||||
{
|
||||
GUIFrame frame = new GUIFrame(new Rectangle(0, 0, 0, 50), Color.Transparent, null, itemList)
|
||||
GUIFrame frame = new GUIFrame(new RectTransform(new Point(itemList.Rect.Width, 50), itemList.Content.RectTransform), style: null)
|
||||
{
|
||||
UserData = fi,
|
||||
Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f),
|
||||
HoverColor = Color.Gold * 0.2f,
|
||||
SelectedColor = Color.Gold * 0.5f,
|
||||
ToolTip = fi.TargetItem.Description
|
||||
};
|
||||
|
||||
GUITextBlock textBlock = new GUITextBlock(
|
||||
new Rectangle(40, 0, 0, 25),
|
||||
fi.TargetItem.Name,
|
||||
Color.Transparent, Color.White,
|
||||
Alignment.Left, Alignment.Left,
|
||||
null, frame);
|
||||
textBlock.ToolTip = fi.TargetItem.Description;
|
||||
textBlock.Padding = new Vector4(5.0f, 0.0f, 5.0f, 0.0f);
|
||||
|
||||
if (fi.TargetItem.sprite != null)
|
||||
GUITextBlock textBlock = new GUITextBlock(new RectTransform(Vector2.Zero, frame.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point(50, 0) },
|
||||
fi.DisplayName)
|
||||
{
|
||||
GUIImage img = new GUIImage(new Rectangle(0, 0, 40, 40), fi.TargetItem.sprite, Alignment.Left, frame);
|
||||
img.Scale = Math.Min(Math.Min(40.0f / img.SourceRect.Width, 40.0f / img.SourceRect.Height), 1.0f);
|
||||
img.Color = fi.TargetItem.SpriteColor;
|
||||
img.ToolTip = fi.TargetItem.Description;
|
||||
ToolTip = fi.TargetItem.Description
|
||||
};
|
||||
|
||||
var itemIcon = fi.TargetItem.InventoryIcon ?? fi.TargetItem.sprite;
|
||||
if (itemIcon != null)
|
||||
{
|
||||
GUIImage img = new GUIImage(new RectTransform(new Point(40, 40), frame.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point(3, 0) },
|
||||
itemIcon, scaleToFit: true)
|
||||
{
|
||||
Color = fi.TargetItem.InventoryIconColor,
|
||||
ToolTip = fi.TargetItem.Description
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
activateButton = new GUIButton(new RectTransform(new Vector2(0.8f, 0.07f), paddedFrame.RectTransform),
|
||||
TextManager.Get("FabricatorCreate"))
|
||||
{
|
||||
OnClicked = StartButtonClicked,
|
||||
UserData = selectedItem,
|
||||
Enabled = false
|
||||
};
|
||||
|
||||
inSufficientPowerWarning = new GUITextBlock(new RectTransform(Vector2.One, activateButton.RectTransform), TextManager.Get("FabricatorNoPower"),
|
||||
textColor: Color.Orange, textAlignment: Alignment.Center, color: Color.Black, style: "OuterGlow")
|
||||
{
|
||||
HoverColor = Color.Black,
|
||||
IgnoreLayoutGroups = true,
|
||||
Visible = false,
|
||||
CanBeFocused = false
|
||||
};
|
||||
}
|
||||
|
||||
partial void OnItemLoadedProjSpecific()
|
||||
{
|
||||
inputContainer.AllowUIOverlap = true;
|
||||
inputContainer.Inventory.RectTransform = inputInventoryHolder.RectTransform;
|
||||
outputContainer.AllowUIOverlap = true;
|
||||
outputContainer.Inventory.RectTransform = outputInventoryHolder.RectTransform;
|
||||
}
|
||||
|
||||
partial void SelectProjSpecific(Character character)
|
||||
{
|
||||
var nonItems = itemList.Content.Children.Where(c => !(c.UserData is FabricableItem)).ToList();
|
||||
nonItems.ForEach(i => itemList.Content.RemoveChild(i));
|
||||
|
||||
itemList.Content.RectTransform.SortChildren((c1, c2) =>
|
||||
{
|
||||
var item1 = c1.GUIComponent.UserData as FabricableItem;
|
||||
var item2 = c2.GUIComponent.UserData as FabricableItem;
|
||||
|
||||
bool hasSkills1 = DegreeOfSuccess(character, item1.RequiredSkills) >= 0.5f;
|
||||
bool hasSkills2 = DegreeOfSuccess(character, item2.RequiredSkills) >= 0.5f;
|
||||
|
||||
if (hasSkills1 != hasSkills2)
|
||||
{
|
||||
return hasSkills1 ? -1 : 1;
|
||||
}
|
||||
|
||||
return string.Compare(item1.DisplayName, item2.DisplayName);
|
||||
});
|
||||
|
||||
var sufficientSkillsText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), itemList.Content.RectTransform), "Sufficient skills to fabricate:", textColor: Color.LightGreen)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
sufficientSkillsText.RectTransform.SetAsFirstChild();
|
||||
|
||||
var insufficientSkillsText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), itemList.Content.RectTransform), "Insufficient skills to fabricate:", textColor: Color.Orange)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
var firstinSufficient = itemList.Content.Children.FirstOrDefault(c => c.UserData is FabricableItem fabricableItem && DegreeOfSuccess(character, fabricableItem.RequiredSkills) < 0.5f);
|
||||
if (firstinSufficient != null)
|
||||
{
|
||||
insufficientSkillsText.RectTransform.RepositionChildInHierarchy(itemList.Content.RectTransform.GetChildIndex(firstinSufficient.RectTransform));
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawInputOverLay(SpriteBatch spriteBatch, GUICustomComponent overlayComponent)
|
||||
{
|
||||
overlayComponent.RectTransform.SetAsLastChild();
|
||||
|
||||
FabricableItem targetItem = fabricatedItem ?? selectedItem;
|
||||
if (targetItem != null)
|
||||
{
|
||||
int slotIndex = 0;
|
||||
|
||||
var missingItems = new List<FabricableItem.RequiredItem>();
|
||||
foreach (FabricableItem.RequiredItem requiredItem in targetItem.RequiredItems)
|
||||
{
|
||||
for (int i = 0; i < requiredItem.Amount; i++)
|
||||
{
|
||||
missingItems.Add(requiredItem);
|
||||
}
|
||||
}
|
||||
foreach (Item item in inputContainer.Inventory.Items)
|
||||
{
|
||||
if (item == null) { continue; }
|
||||
missingItems.Remove(missingItems.FirstOrDefault(mi => mi.ItemPrefab == item.prefab));
|
||||
}
|
||||
|
||||
var availableIngredients = GetAvailableIngredients();
|
||||
|
||||
foreach (FabricableItem.RequiredItem requiredItem in missingItems)
|
||||
{
|
||||
//highlight suitable ingredients in linked inventories
|
||||
foreach (Item item in availableIngredients)
|
||||
{
|
||||
if (item.ParentInventory != inputContainer.Inventory && IsItemValidIngredient(item, requiredItem))
|
||||
{
|
||||
int availableSlotIndex = Array.IndexOf(item.ParentInventory.Items, item);
|
||||
if (item.ParentInventory.slots[availableSlotIndex].HighlightTimer <= 0.0f)
|
||||
{
|
||||
item.ParentInventory.slots[availableSlotIndex].ShowBorderHighlight(Color.LightGreen * 0.5f, 0.5f, 0.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (slotIndex < inputContainer.Capacity && inputContainer.Inventory.Items[slotIndex] != null)
|
||||
{
|
||||
slotIndex++;
|
||||
}
|
||||
if (slotIndex >= inputContainer.Capacity) { break; }
|
||||
|
||||
var itemIcon = requiredItem.ItemPrefab.InventoryIcon ?? requiredItem.ItemPrefab.sprite;
|
||||
|
||||
Rectangle slotRect = inputContainer.Inventory.slots[slotIndex].Rect;
|
||||
|
||||
itemIcon.Draw(
|
||||
spriteBatch,
|
||||
slotRect.Center.ToVector2(),
|
||||
color: requiredItem.ItemPrefab.InventoryIconColor * 0.3f,
|
||||
scale: Math.Min(slotRect.Width / itemIcon.size.X, slotRect.Height / itemIcon.size.Y));
|
||||
|
||||
if (slotRect.Contains(PlayerInput.MousePosition))
|
||||
{
|
||||
string toolTipText = requiredItem.ItemPrefab.Name;
|
||||
if (!string.IsNullOrEmpty(requiredItem.ItemPrefab.Description))
|
||||
{
|
||||
toolTipText += '\n' + requiredItem.ItemPrefab.Description;
|
||||
}
|
||||
tooltip = new Pair<Rectangle, string>(slotRect, toolTipText);
|
||||
}
|
||||
|
||||
slotIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawOutputOverLay(SpriteBatch spriteBatch, GUICustomComponent overlayComponent)
|
||||
{
|
||||
overlayComponent.RectTransform.SetAsLastChild();
|
||||
|
||||
FabricableItem targetItem = fabricatedItem ?? selectedItem;
|
||||
if (targetItem != null)
|
||||
{
|
||||
var itemIcon = targetItem.TargetItem.InventoryIcon ?? targetItem.TargetItem.sprite;
|
||||
|
||||
Rectangle slotRect = outputContainer.Inventory.slots[0].Rect;
|
||||
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
new Rectangle(
|
||||
slotRect.X, slotRect.Y + (int)(slotRect.Height * (1.0f - progressState)),
|
||||
slotRect.Width, (int)(slotRect.Height * progressState)),
|
||||
Color.Green * 0.5f, isFilled: true);
|
||||
|
||||
itemIcon.Draw(
|
||||
spriteBatch,
|
||||
slotRect.Center.ToVector2(),
|
||||
color: targetItem.TargetItem.InventoryIconColor * 0.4f,
|
||||
scale: Math.Min(slotRect.Width / itemIcon.size.X, slotRect.Height / itemIcon.size.Y) * 0.9f);
|
||||
}
|
||||
|
||||
if (tooltip != null)
|
||||
{
|
||||
GUIComponent.DrawToolTip(spriteBatch, tooltip.Second, tooltip.First);
|
||||
tooltip = null;
|
||||
}
|
||||
}
|
||||
|
||||
private bool SelectItem(GUIComponent component, object obj)
|
||||
{
|
||||
FabricableItem targetItem = obj as FabricableItem;
|
||||
if (targetItem == null) return false;
|
||||
selectedItem = obj as FabricableItem;
|
||||
if (selectedItem == null) return false;
|
||||
|
||||
if (selectedItemFrame != null) GuiFrame.RemoveChild(selectedItemFrame);
|
||||
selectedItemFrame.ClearChildren();
|
||||
|
||||
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), selectedItemFrame.RectTransform, Anchor.Center)) { RelativeSpacing = 0.03f, Stretch = true };
|
||||
|
||||
//int width = 200, height = 150;
|
||||
selectedItemFrame = new GUIFrame(new Rectangle(0, 0, (int)(GuiFrame.Rect.Width * 0.4f), 350), Color.Black * 0.8f, Alignment.CenterY | Alignment.Right, null, GuiFrame);
|
||||
|
||||
selectedItemFrame.Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f);
|
||||
|
||||
progressBar = new GUIProgressBar(new Rectangle(0, 0, 0, 20), Color.Green, "", 0.0f, Alignment.BottomCenter, selectedItemFrame);
|
||||
progressBar.IsHorizontal = true;
|
||||
|
||||
if (targetItem.TargetItem.sprite != null)
|
||||
/*var itemIcon = selectedItem.TargetItem.InventoryIcon ?? selectedItem.TargetItem.sprite;
|
||||
if (itemIcon != null)
|
||||
{
|
||||
int y = 0;
|
||||
|
||||
GUIImage img = new GUIImage(new Rectangle(10, 0, 40, 40), targetItem.TargetItem.sprite, Alignment.TopLeft, selectedItemFrame);
|
||||
img.Scale = Math.Min(Math.Min(40.0f / img.SourceRect.Width, 40.0f / img.SourceRect.Height), 1.0f);
|
||||
img.Color = targetItem.TargetItem.SpriteColor;
|
||||
|
||||
new GUITextBlock(
|
||||
new Rectangle(60, 0, 0, 25),
|
||||
targetItem.TargetItem.Name,
|
||||
Color.Transparent, Color.White,
|
||||
Alignment.TopLeft,
|
||||
Alignment.TopLeft, null,
|
||||
selectedItemFrame, true);
|
||||
|
||||
y += 40;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(targetItem.TargetItem.Description))
|
||||
GUIImage img = new GUIImage(new RectTransform(new Point(40, 40), paddedFrame.RectTransform),
|
||||
itemIcon, scaleToFit: true)
|
||||
{
|
||||
var description = new GUITextBlock(
|
||||
new Rectangle(0, y, 0, 0),
|
||||
targetItem.TargetItem.Description,
|
||||
"", Alignment.TopLeft, Alignment.TopLeft,
|
||||
selectedItemFrame, true, GUI.SmallFont);
|
||||
Color = selectedItem.TargetItem.InventoryIconColor
|
||||
};
|
||||
}*/
|
||||
var nameBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform),
|
||||
selectedItem.TargetItem.Name, textAlignment: Alignment.CenterLeft);
|
||||
|
||||
y += description.Rect.Height + 10;
|
||||
}
|
||||
|
||||
|
||||
List<Skill> inadequateSkills = new List<Skill>();
|
||||
|
||||
if (Character.Controlled != null)
|
||||
if (!string.IsNullOrWhiteSpace(selectedItem.TargetItem.Description))
|
||||
{
|
||||
var description = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform),
|
||||
selectedItem.TargetItem.Description,
|
||||
font: GUI.SmallFont, wrap: true);
|
||||
if (description.Rect.Height > paddedFrame.Rect.Height * 0.4f)
|
||||
{
|
||||
inadequateSkills = targetItem.RequiredSkills.FindAll(skill => Character.Controlled.GetSkillLevel(skill.Name) < skill.Level);
|
||||
description.Wrap = false;
|
||||
description.Text = description.WrappedText.Split('\n').First()+"...";
|
||||
nameBlock.ToolTip = description.ToolTip = selectedItem.TargetItem.Description;
|
||||
description.RectTransform.MaxSize = new Point(int.MaxValue, (int)description.Font.MeasureString(description.Text).Y);
|
||||
}
|
||||
|
||||
string text = TextManager.Get("FabricatorRequiredItems")+ ":\n";
|
||||
foreach (Tuple<ItemPrefab, int, float, bool> ip in targetItem.RequiredItems)
|
||||
}
|
||||
|
||||
List<Skill> inadequateSkills = new List<Skill>();
|
||||
if (Character.Controlled != null)
|
||||
{
|
||||
inadequateSkills = selectedItem.RequiredSkills.FindAll(skill => Character.Controlled.GetSkillLevel(skill.Identifier) < skill.Level);
|
||||
}
|
||||
|
||||
if (selectedItem.RequiredSkills.Any())
|
||||
{
|
||||
string text = TextManager.Get("FabricatorRequiredSkills") + ":\n";
|
||||
foreach (Skill skill in selectedItem.RequiredSkills)
|
||||
{
|
||||
text += " - " + ip.Item1.Name + " x" + ip.Item2 + (ip.Item3 < 1.0f ? ", " + ip.Item3 * 100 + "% " + TextManager.Get("FabricatorRequiredCondition") + "\n" : "\n");
|
||||
text += " - " + TextManager.Get("SkillName." + skill.Identifier) + " " + TextManager.Get("Lvl").ToLower() + " " + skill.Level;
|
||||
if (skill != selectedItem.RequiredSkills.Last()) { text += "\n"; }
|
||||
}
|
||||
text += TextManager.Get("FabricatorRequiredTime") + ": " + targetItem.RequiredTime + " s\n";
|
||||
|
||||
var requiredItemsText = new GUITextBlock(
|
||||
new Rectangle(0, y, 0, 0),
|
||||
text,
|
||||
Color.Transparent, Color.White,
|
||||
Alignment.TopLeft,
|
||||
Alignment.TopLeft, null,
|
||||
selectedItemFrame,
|
||||
font: GUI.SmallFont);
|
||||
|
||||
|
||||
if (targetItem.RequiredSkills.Any())
|
||||
{
|
||||
text = TextManager.Get("FabricatorRequiredSkills") + ":\n";
|
||||
foreach (Skill skill in inadequateSkills)
|
||||
{
|
||||
text += " - " + skill.Name + " " + TextManager.Get("Lvl").ToLower() + " " + skill.Level + "\n";
|
||||
}
|
||||
new GUITextBlock(
|
||||
new Rectangle(0, y + requiredItemsText.Rect.Height, 0, 0),
|
||||
text,
|
||||
Color.Transparent, inadequateSkills.Any() ? Color.Red : Color.White,
|
||||
Alignment.TopLeft,
|
||||
Alignment.TopLeft, null,
|
||||
selectedItemFrame,
|
||||
font: GUI.SmallFont);
|
||||
}
|
||||
|
||||
|
||||
activateButton = new GUIButton(new Rectangle(0, -30, 100, 20), TextManager.Get("FabricatorCreate"), Color.White, Alignment.CenterX | Alignment.Bottom, "", selectedItemFrame);
|
||||
activateButton.OnClicked = StartButtonClicked;
|
||||
activateButton.UserData = targetItem;
|
||||
activateButton.Enabled = false;
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform), text,
|
||||
textColor: inadequateSkills.Any() ? Color.Red : Color.LightGreen, font: GUI.SmallFont);
|
||||
}
|
||||
|
||||
float degreeOfSuccess = DegreeOfSuccess(Character.Controlled, selectedItem.RequiredSkills);
|
||||
if (degreeOfSuccess > 0.5f) { degreeOfSuccess = 1.0f; }
|
||||
|
||||
float requiredTime = GetRequiredTime(selectedItem, Character.Controlled);
|
||||
string requiredTimeText = TextManager.Get("FabricatorRequiredTime") + ": " + ToolBox.SecondsToReadableTime(requiredTime);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform),
|
||||
requiredTimeText, textColor: ToolBox.GradientLerp(degreeOfSuccess, Color.Red, Color.Yellow, Color.LightGreen), font: GUI.SmallFont);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool StartButtonClicked(GUIButton button, object obj)
|
||||
{
|
||||
if (selectedItem == null) { return false; }
|
||||
if (fabricatedItem == null)
|
||||
{
|
||||
StartFabricating(obj as FabricableItem, Character.Controlled);
|
||||
StartFabricating(selectedItem, Character.Controlled);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -173,49 +335,29 @@ namespace Barotrauma.Items.Components
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
||||
{
|
||||
GuiFrame.Draw(spriteBatch);
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
{
|
||||
GuiFrame.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
public override void UpdateHUD(Character character)
|
||||
{
|
||||
FabricableItem targetItem = itemList.SelectedData as FabricableItem;
|
||||
if (targetItem != null)
|
||||
{
|
||||
activateButton.Enabled = CanBeFabricated(targetItem, character);
|
||||
}
|
||||
activateButton.Enabled = false;
|
||||
inSufficientPowerWarning.Visible = powerConsumption > 0 && voltage < minVoltage;
|
||||
|
||||
var availableIngredients = GetAvailableIngredients();
|
||||
if (character != null)
|
||||
{
|
||||
bool itemsChanged = false;
|
||||
if (prevContainedItems == null)
|
||||
foreach (GUIComponent child in itemList.Content.Children)
|
||||
{
|
||||
itemsChanged = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var itemContainer = item.GetComponent<ItemContainer>();
|
||||
for (int i = 0; i < itemContainer.Inventory.Items.Length; i++)
|
||||
var itemPrefab = child.UserData as FabricableItem;
|
||||
if (itemPrefab == null) continue;
|
||||
|
||||
bool canBeFabricated = CanBeFabricated(itemPrefab, availableIngredients);
|
||||
if (itemPrefab == selectedItem)
|
||||
{
|
||||
if (prevContainedItems[i] != itemContainer.Inventory.Items[i])
|
||||
{
|
||||
itemsChanged = true;
|
||||
break;
|
||||
}
|
||||
activateButton.Enabled = canBeFabricated;
|
||||
}
|
||||
|
||||
child.GetChild<GUITextBlock>().TextColor = Color.White * (canBeFabricated ? 1.0f : 0.5f);
|
||||
child.GetChild<GUIImage>().Color = itemPrefab.TargetItem.InventoryIconColor * (canBeFabricated ? 1.0f : 0.5f);
|
||||
}
|
||||
|
||||
if (itemsChanged) CheckFabricableItems(character);
|
||||
}
|
||||
|
||||
|
||||
GuiFrame.Update((float)Timing.Step);
|
||||
}
|
||||
|
||||
public void ClientWrite(NetBuffer msg, object[] extraData = null)
|
||||
@@ -227,8 +369,10 @@ namespace Barotrauma.Items.Components
|
||||
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
|
||||
{
|
||||
int itemIndex = msg.ReadRangedInteger(-1, fabricableItems.Count - 1);
|
||||
UInt16 userID = msg.ReadUInt16();
|
||||
Character user = Entity.FindEntityByID(userID) as Character;
|
||||
|
||||
if (itemIndex == -1)
|
||||
if (itemIndex == -1 || user == null)
|
||||
{
|
||||
CancelFabricating();
|
||||
}
|
||||
@@ -239,7 +383,7 @@ namespace Barotrauma.Items.Components
|
||||
if (itemIndex < 0 || itemIndex >= fabricableItems.Count) return;
|
||||
|
||||
SelectItem(null, fabricableItems[itemIndex]);
|
||||
StartFabricating(fabricableItems[itemIndex]);
|
||||
StartFabricating(fabricableItems[itemIndex], user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,126 +1,225 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Barotrauma.Extensions;
|
||||
using FarseerPhysics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class MiniMap : Powered
|
||||
{
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
private GUIFrame submarineContainer;
|
||||
|
||||
private GUIFrame hullInfoFrame;
|
||||
|
||||
private GUITextBlock hullNameText, hullBreachText, hullAirQualityText, hullWaterText;
|
||||
|
||||
private List<Submarine> displayedSubs = new List<Submarine>();
|
||||
|
||||
partial void InitProjSpecific(XElement element)
|
||||
{
|
||||
new GUICustomComponent(new RectTransform(new Vector2(0.9f, 0.85f), GuiFrame.RectTransform, Anchor.Center),
|
||||
DrawHUDBack, null);
|
||||
submarineContainer = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.85f), GuiFrame.RectTransform, Anchor.Center), style: null);
|
||||
|
||||
hullInfoFrame = new GUIFrame(new RectTransform(new Vector2(0.13f, 0.13f), GUI.Canvas, minSize: new Point(250, 150)),
|
||||
style: "InnerFrame")
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
var hullInfoContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), hullInfoFrame.RectTransform, Anchor.Center))
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.05f
|
||||
};
|
||||
|
||||
hullNameText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.4f), hullInfoContainer.RectTransform), "");
|
||||
hullBreachText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), hullInfoContainer.RectTransform), "");
|
||||
hullAirQualityText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), hullInfoContainer.RectTransform), "");
|
||||
hullWaterText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), hullInfoContainer.RectTransform), "");
|
||||
|
||||
hullInfoFrame.Children.ForEach(c => { c.CanBeFocused = false; c.Children.ForEach(c2 => c2.CanBeFocused = false); });
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
{
|
||||
base.AddToGUIUpdateList();
|
||||
if (hasPower) hullInfoFrame.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
public override void OnMapLoaded()
|
||||
{
|
||||
base.OnMapLoaded();
|
||||
CreateHUD();
|
||||
}
|
||||
|
||||
private void CreateHUD()
|
||||
{
|
||||
submarineContainer.ClearChildren();
|
||||
|
||||
if (item.Submarine == null) return;
|
||||
|
||||
int width = GuiFrame.Rect.Width, height = GuiFrame.Rect.Height;
|
||||
int x = GuiFrame.Rect.X;
|
||||
int y = GuiFrame.Rect.Y;
|
||||
item.Submarine.CreateMiniMap(submarineContainer);
|
||||
displayedSubs.Clear();
|
||||
displayedSubs.Add(item.Submarine);
|
||||
displayedSubs.AddRange(item.Submarine.DockedTo);
|
||||
}
|
||||
|
||||
GuiFrame.Draw(spriteBatch);
|
||||
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
||||
{
|
||||
//recreate HUD if the subs we should display have changed
|
||||
if ((item.Submarine == null && displayedSubs.Count > 0) || //item not inside a sub anymore, but display is still showing subs
|
||||
!displayedSubs.Contains(item.Submarine) || //current sub not displayer
|
||||
item.Submarine.DockedTo.Any(s => !displayedSubs.Contains(s)) || //some of the docked subs not diplayed
|
||||
displayedSubs.Any(s => s != item.Submarine && !item.Submarine.DockedTo.Contains(s))) //displaying a sub that shouldn't be displayed
|
||||
{
|
||||
CreateHUD();
|
||||
}
|
||||
|
||||
if (!hasPower) return;
|
||||
float distort = 1.0f - item.Condition / 100.0f;
|
||||
foreach (HullData hullData in hullDatas.Values)
|
||||
{
|
||||
hullData.DistortionTimer -= deltaTime;
|
||||
if (hullData.DistortionTimer <= 0.0f)
|
||||
{
|
||||
hullData.Distort = Rand.Range(0.0f, 1.0f) < distort * distort;
|
||||
if (hullData.Distort)
|
||||
{
|
||||
hullData.Oxygen = Rand.Range(0.0f, 100.0f);
|
||||
hullData.Water = Rand.Range(0.0f, 1.0f);
|
||||
}
|
||||
hullData.DistortionTimer = Rand.Range(1.0f, 10.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle miniMap = new Rectangle(x + 20, y + 40, width - 40, height - 60);
|
||||
private void DrawHUDBack(SpriteBatch spriteBatch, GUICustomComponent container)
|
||||
{
|
||||
hullInfoFrame.Visible = false;
|
||||
if (item.Submarine == null || !hasPower)
|
||||
{
|
||||
foreach (Hull hull in Hull.hullList)
|
||||
{
|
||||
var hullFrame = submarineContainer.Children.First().FindChild(hull);
|
||||
if (hullFrame == null) continue;
|
||||
|
||||
float size = Math.Min((float)miniMap.Width / (float)item.Submarine.Borders.Width, (float)miniMap.Height / (float)item.Submarine.Borders.Height);
|
||||
hullFrame.Color = Color.DarkCyan * 0.3f;
|
||||
hullFrame.Children.First().Color = Color.DarkCyan * 0.3f;
|
||||
}
|
||||
}
|
||||
|
||||
float scale = 1.0f;
|
||||
HashSet<Submarine> subs = new HashSet<Submarine>();
|
||||
foreach (Hull hull in Hull.hullList)
|
||||
{
|
||||
Point topLeft = new Point(
|
||||
miniMap.X + (int)((hull.Rect.X - item.Submarine.HiddenSubPosition.X - item.Submarine.Borders.X) * size),
|
||||
miniMap.Y - (int)((hull.Rect.Y - item.Submarine.HiddenSubPosition.Y - item.Submarine.Borders.Y) * size));
|
||||
if (hull.Submarine == null) continue;
|
||||
var hullFrame = submarineContainer.Children.First().FindChild(hull);
|
||||
if (hullFrame == null) continue;
|
||||
|
||||
Point bottomRight = new Point(
|
||||
topLeft.X + (int)(hull.Rect.Width * size),
|
||||
topLeft.Y + (int)(hull.Rect.Height * size));
|
||||
|
||||
topLeft.X = (int)MathUtils.RoundTowardsClosest(topLeft.X, 4);
|
||||
topLeft.Y = (int)MathUtils.RoundTowardsClosest(topLeft.Y, 4);
|
||||
bottomRight.X = (int)MathUtils.RoundTowardsClosest(bottomRight.X, 4);
|
||||
bottomRight.Y = (int)MathUtils.RoundTowardsClosest(bottomRight.Y, 4);
|
||||
|
||||
Rectangle hullRect = new Rectangle(
|
||||
topLeft, bottomRight - topLeft);
|
||||
|
||||
HullData hullData;
|
||||
hullDatas.TryGetValue(hull, out hullData);
|
||||
|
||||
Color borderColor = Color.Green;
|
||||
|
||||
|
||||
//hull integrity -----------------------------------
|
||||
hullDatas.TryGetValue(hull, out HullData hullData);
|
||||
if (hullData == null)
|
||||
{
|
||||
hullData = new HullData();
|
||||
hullDatas.Add(hull, hullData);
|
||||
}
|
||||
|
||||
if (hullData.Distort)
|
||||
{
|
||||
hullFrame.Children.First().Color = Color.Lerp(Color.Black, Color.DarkGray * 0.5f, Rand.Range(0.0f, 1.0f));
|
||||
hullFrame.Color = Color.DarkGray * 0.5f;
|
||||
continue;
|
||||
}
|
||||
|
||||
subs.Add(hull.Submarine);
|
||||
scale = Math.Min(
|
||||
hullFrame.Parent.Rect.Width / (float)hull.Submarine.Borders.Width,
|
||||
hullFrame.Parent.Rect.Height / (float)hull.Submarine.Borders.Height);
|
||||
|
||||
Color borderColor = Color.DarkCyan;
|
||||
|
||||
float? gapOpenSum = 0.0f;
|
||||
if (ShowHullIntegrity)
|
||||
{
|
||||
gapOpenSum = hull.ConnectedGaps.Where(g => !g.IsRoomToRoom).Sum(g => g.Open);
|
||||
borderColor = Color.Lerp(borderColor, Color.Red, Math.Min((float)gapOpenSum, 1.0f));
|
||||
borderColor = Color.Lerp(Color.DarkCyan, Color.Red, Math.Min((float)gapOpenSum, 1.0f));
|
||||
}
|
||||
|
||||
//oxygen -----------------------------------
|
||||
|
||||
float? oxygenAmount = null;
|
||||
if (RequireOxygenDetectors && (hullData == null || hullData.Oxygen == null))
|
||||
if (!RequireOxygenDetectors || hullData?.Oxygen != null)
|
||||
{
|
||||
borderColor *= 0.5f;
|
||||
oxygenAmount = RequireOxygenDetectors ? hullData.Oxygen : hull.OxygenPercentage;
|
||||
GUI.DrawRectangle(spriteBatch, hullFrame.Rect, Color.Lerp(Color.Red * 0.5f, Color.Green * 0.3f, (float)oxygenAmount / 100.0f), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
oxygenAmount = hullData != null && hullData.Oxygen != null ? (float)hullData.Oxygen : hull.OxygenPercentage;
|
||||
GUI.DrawRectangle(spriteBatch, hullRect, Color.Lerp(Color.Red * 0.5f, Color.Green * 0.3f, (float)oxygenAmount / 100.0f), true);
|
||||
}
|
||||
|
||||
//water -----------------------------------
|
||||
|
||||
float? waterAmount = null;
|
||||
if (RequireWaterDetectors && (hullData == null || hullData.Water == null))
|
||||
if (!RequireWaterDetectors || hullData.Water != null)
|
||||
{
|
||||
borderColor *= 0.5f;
|
||||
}
|
||||
else
|
||||
{
|
||||
waterAmount = hullData != null && hullData.Water != null ?
|
||||
(float)hullData.Water :
|
||||
Math.Min(hull.WaterVolume / hull.Volume, 1.0f);
|
||||
|
||||
if (hullRect.Height * waterAmount > 3.0f)
|
||||
waterAmount = RequireWaterDetectors ? hullData.Water : Math.Min(hull.WaterVolume / hull.Volume, 1.0f);
|
||||
if (hullFrame.Rect.Height * waterAmount > 3.0f)
|
||||
{
|
||||
Rectangle waterRect = new Rectangle(
|
||||
hullRect.X,
|
||||
(int)(hullRect.Y + hullRect.Height * (1.0f - waterAmount)),
|
||||
hullRect.Width,
|
||||
(int)(hullRect.Height * waterAmount));
|
||||
hullFrame.Rect.X, (int)(hullFrame.Rect.Y + hullFrame.Rect.Height * (1.0f - waterAmount)),
|
||||
hullFrame.Rect.Width, (int)(hullFrame.Rect.Height * waterAmount));
|
||||
|
||||
waterRect.Inflate(-3, -3);
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, waterRect, Color.DarkBlue, true);
|
||||
GUI.DrawRectangle(spriteBatch, waterRect, new Color(85, 136, 147), true);
|
||||
GUI.DrawLine(spriteBatch, new Vector2(waterRect.X, waterRect.Y), new Vector2(waterRect.Right, waterRect.Y), Color.LightBlue);
|
||||
}
|
||||
}
|
||||
|
||||
if (hullRect.Contains(PlayerInput.MousePosition))
|
||||
if (GUI.MouseOn == hullFrame || hullFrame.IsParentOf(GUI.MouseOn))
|
||||
{
|
||||
borderColor = Color.White;
|
||||
hullInfoFrame.RectTransform.ScreenSpaceOffset = hullFrame.Rect.Center;
|
||||
|
||||
if (gapOpenSum > 0.1f)
|
||||
{
|
||||
GUI.DrawString(spriteBatch,
|
||||
new Vector2(x + 10, y + height - 60),
|
||||
TextManager.Get("MiniMapHullBreach"), Color.Red, Color.Black * 0.5f, 2, GUI.SmallFont);
|
||||
}
|
||||
hullInfoFrame.Visible = true;
|
||||
hullNameText.Text = hull.RoomName;
|
||||
|
||||
GUI.DrawString(spriteBatch,
|
||||
new Vector2(x + 10, y + height - 60),
|
||||
oxygenAmount == null ? TextManager.Get("MiniMapAirQualityUnavailable") : TextManager.Get("MiniMapAirQuality") + ": " + (int)oxygenAmount + " %",
|
||||
oxygenAmount == null ? Color.Red : Color.Lerp(Color.Red, Color.LightGreen, (float)oxygenAmount / 100.0f),
|
||||
Color.Black * 0.5f, 2, GUI.SmallFont);
|
||||
hullBreachText.Text = gapOpenSum > 0.1f ? TextManager.Get("MiniMapHullBreach") : "";
|
||||
hullBreachText.TextColor = Color.Red;
|
||||
|
||||
GUI.DrawString(spriteBatch,
|
||||
new Vector2(x + 10, y + height - 40),
|
||||
waterAmount == null ? TextManager.Get("MiniMapWaterLevelUnavailable") : TextManager.Get("MiniMapWaterLevel") + ": " + (int)(waterAmount * 100.0f) + " %",
|
||||
waterAmount == null ? Color.Red : Color.Lerp(Color.LightGreen, Color.Red, (float)waterAmount),
|
||||
Color.Black * 0.5f, 2, GUI.SmallFont);
|
||||
hullAirQualityText.Text = oxygenAmount == null ? TextManager.Get("MiniMapAirQualityUnavailable") : TextManager.Get("MiniMapAirQuality") + ": " + (int)oxygenAmount + " %";
|
||||
hullAirQualityText.TextColor = oxygenAmount == null ? Color.Red : Color.Lerp(Color.Red, Color.LightGreen, (float)oxygenAmount / 100.0f);
|
||||
|
||||
hullWaterText.Text = waterAmount == null ? TextManager.Get("MiniMapWaterLevelUnavailable") : TextManager.Get("MiniMapWaterLevel") + ": " + (int)(waterAmount * 100.0f) + " %";
|
||||
hullWaterText.TextColor = waterAmount == null ? Color.Red : Color.Lerp(Color.LightGreen, Color.Red, (float)waterAmount);
|
||||
|
||||
borderColor = Color.Lerp(borderColor, Color.White, 0.5f);
|
||||
hullFrame.Children.First().Color = Color.White;
|
||||
}
|
||||
else
|
||||
{
|
||||
hullFrame.Children.First().Color = Color.DarkCyan * 0.8f;
|
||||
}
|
||||
hullFrame.Color = borderColor;
|
||||
}
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, hullRect, borderColor, false, 0.0f, 2);
|
||||
foreach (Submarine sub in subs)
|
||||
{
|
||||
if (sub.HullVertices == null) { continue; }
|
||||
|
||||
Rectangle worldBorders = sub.GetDockedBorders();
|
||||
worldBorders.Location += sub.WorldPosition.ToPoint();
|
||||
|
||||
scale = Math.Min(
|
||||
submarineContainer.Rect.Width / (float)worldBorders.Width,
|
||||
submarineContainer.Rect.Height / (float)worldBorders.Height) * 0.9f;
|
||||
|
||||
float displayScale = ConvertUnits.ToDisplayUnits(scale);
|
||||
Vector2 offset = ConvertUnits.ToSimUnits(sub.WorldPosition - new Vector2(worldBorders.Center.X, worldBorders.Y - worldBorders.Height / 2));
|
||||
Vector2 center = container.Rect.Center.ToVector2();
|
||||
|
||||
for (int i = 0; i < sub.HullVertices.Count; i++)
|
||||
{
|
||||
Vector2 start = (sub.HullVertices[i] + offset) * displayScale;
|
||||
start.Y = -start.Y;
|
||||
Vector2 end = (sub.HullVertices[(i + 1) % sub.HullVertices.Count] + offset) * displayScale;
|
||||
end.Y = -end.Y;
|
||||
GUI.DrawLine(spriteBatch, center + start, center + end, Color.DarkCyan * Rand.Range(0.3f, 0.35f), width: 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,62 @@
|
||||
using Barotrauma.Networking;
|
||||
using Barotrauma.Particles;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class Pump : Powered, IServerSerializable, IClientSerializable
|
||||
{
|
||||
private GUITickBox isActiveTickBox;
|
||||
private GUIScrollBar isActiveSlider;
|
||||
private GUIScrollBar pumpSpeedSlider;
|
||||
private GUITickBox powerIndicator;
|
||||
|
||||
partial void InitProjSpecific()
|
||||
private List<Pair<Vector2, ParticleEmitter>> pumpOutEmitters = new List<Pair<Vector2, ParticleEmitter>>();
|
||||
private List<Pair<Vector2, ParticleEmitter>> pumpInEmitters = new List<Pair<Vector2, ParticleEmitter>>();
|
||||
|
||||
partial void InitProjSpecific(XElement element)
|
||||
{
|
||||
isActiveTickBox = new GUITickBox(new Rectangle(0, 0, 20, 20), TextManager.Get("PumpRunning"), Alignment.TopLeft, GuiFrame);
|
||||
isActiveTickBox.OnSelected = (GUITickBox box) =>
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "pumpoutemitter":
|
||||
pumpOutEmitters.Add(new Pair<Vector2, ParticleEmitter>(
|
||||
subElement.GetAttributeVector2("position", Vector2.Zero),
|
||||
new ParticleEmitter(subElement)));
|
||||
break;
|
||||
case "pumpinemitter":
|
||||
pumpInEmitters.Add(new Pair<Vector2, ParticleEmitter>(
|
||||
subElement.GetAttributeVector2("position", Vector2.Zero),
|
||||
new ParticleEmitter(subElement)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (GuiFrame == null) { return; }
|
||||
|
||||
GUIFrame paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.8f), GuiFrame.RectTransform, Anchor.Center), style: null);
|
||||
|
||||
isActiveSlider = new GUIScrollBar(new RectTransform(new Point(50, 100), paddedFrame.RectTransform, Anchor.CenterLeft),
|
||||
barSize: 0.2f, style: "OnOffLever")
|
||||
{
|
||||
IsBooleanSwitch = true,
|
||||
MinValue = 0.25f,
|
||||
MaxValue = 0.75f
|
||||
};
|
||||
var sliderHandle = isActiveSlider.GetChild<GUIButton>();
|
||||
sliderHandle.RectTransform.NonScaledSize = new Point(84, sliderHandle.Rect.Height);
|
||||
|
||||
isActiveSlider.OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
|
||||
{
|
||||
bool active = scrollBar.BarScroll < 0.5f;
|
||||
if (active == IsActive) return false;
|
||||
|
||||
targetLevel = null;
|
||||
IsActive = !IsActive;
|
||||
IsActive = active;
|
||||
if (!IsActive) currPowerConsumption = 0.0f;
|
||||
|
||||
if (GameMain.Server != null)
|
||||
@@ -31,66 +73,102 @@ namespace Barotrauma.Items.Components
|
||||
return true;
|
||||
};
|
||||
|
||||
var button = new GUIButton(new Rectangle(160, 40, 35, 30), TextManager.Get("PumpOut"), "", GuiFrame);
|
||||
button.OnClicked = (GUIButton btn, object obj) =>
|
||||
var rightArea = new GUILayoutGroup(new RectTransform(new Vector2(0.75f, 1.0f), paddedFrame.RectTransform, Anchor.CenterRight)) { RelativeSpacing = 0.1f };
|
||||
|
||||
powerIndicator = new GUITickBox(new RectTransform(new Point(30, 30), rightArea.RectTransform), TextManager.Get("PumpPowered"), style: "IndicatorLightGreen")
|
||||
{
|
||||
FlowPercentage -= 10.0f;
|
||||
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
GameServer.Log(Character.Controlled.LogName + " set the pumping speed of " + item.Name + " to " + (int)(flowPercentage) + " %", ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
else if (GameMain.Client != null)
|
||||
{
|
||||
correctionTimer = CorrectionDelay;
|
||||
item.CreateClientEvent(this);
|
||||
}
|
||||
|
||||
return true;
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
button = new GUIButton(new Rectangle(210, 40, 35, 30), TextManager.Get("PumpIn"), "", GuiFrame);
|
||||
button.OnClicked = (GUIButton btn, object obj) =>
|
||||
var pumpSpeedText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), rightArea.RectTransform) { RelativeOffset = new Vector2(0.25f, 0.0f) },
|
||||
"", textAlignment: Alignment.BottomLeft);
|
||||
string pumpSpeedStr = TextManager.Get("PumpSpeed");
|
||||
pumpSpeedText.TextGetter = () => { return pumpSpeedStr + ": " + (int)flowPercentage + " %"; };
|
||||
|
||||
var sliderArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.3f), rightArea.RectTransform, Anchor.CenterLeft), isHorizontal: true)
|
||||
{
|
||||
FlowPercentage += 10.0f;
|
||||
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
GameServer.Log(Character.Controlled.LogName + " set the pumping speed of " + item.Name + " to " + (int)(flowPercentage) + " %", ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
else if (GameMain.Client != null)
|
||||
{
|
||||
correctionTimer = CorrectionDelay;
|
||||
item.CreateClientEvent(this);
|
||||
}
|
||||
|
||||
return true;
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.05f
|
||||
};
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), sliderArea.RectTransform),
|
||||
TextManager.Get("PumpOut"), textAlignment: Alignment.Center);
|
||||
pumpSpeedSlider = new GUIScrollBar(new RectTransform(new Vector2(0.8f, 1.0f), sliderArea.RectTransform), barSize: 0.25f, style: "GUISlider")
|
||||
{
|
||||
Step = 0.05f,
|
||||
OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
|
||||
{
|
||||
float newValue = barScroll * 200.0f - 100.0f;
|
||||
if (Math.Abs(newValue - FlowPercentage) < 0.1f) return false;
|
||||
|
||||
FlowPercentage = newValue;
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
GameServer.Log(Character.Controlled.LogName + " set the pumping speed of " + item.Name + " to " + (int)(flowPercentage) + " %", ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
else if (GameMain.Client != null)
|
||||
{
|
||||
correctionTimer = CorrectionDelay;
|
||||
item.CreateClientEvent(this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), sliderArea.RectTransform),
|
||||
TextManager.Get("PumpIn"), textAlignment: Alignment.Center);
|
||||
}
|
||||
|
||||
public override void OnItemLoaded()
|
||||
{
|
||||
if (pumpSpeedSlider != null)
|
||||
{
|
||||
pumpSpeedSlider.BarScroll = (flowPercentage + 100.0f) / 200.0f;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
partial void UpdateProjSpecific(float deltaTime)
|
||||
{
|
||||
int x = GuiFrame.Rect.X;
|
||||
int y = GuiFrame.Rect.Y;
|
||||
|
||||
GuiFrame.Draw(spriteBatch);
|
||||
|
||||
GUI.Font.DrawString(spriteBatch, TextManager.Get("PumpSpeed") + ": " + (int)flowPercentage + " %", new Vector2(x + 40, y + 85), Color.White);
|
||||
if (FlowPercentage < 0.0f)
|
||||
{
|
||||
foreach (Pair<Vector2, ParticleEmitter> pumpOutEmitter in pumpOutEmitters)
|
||||
{
|
||||
//only emit "pump out" particles when underwater
|
||||
Vector2 particlePos = item.Rect.Location.ToVector2() + pumpOutEmitter.First;
|
||||
if (item.CurrentHull != null && item.CurrentHull.Surface < particlePos.Y) continue;
|
||||
|
||||
pumpOutEmitter.Second.Emit(deltaTime, item.WorldRect.Location.ToVector2() + pumpOutEmitter.First * item.Scale, item.CurrentHull,
|
||||
velocityMultiplier: MathHelper.Lerp(0.5f, 1.0f, -FlowPercentage / 100.0f));
|
||||
}
|
||||
}
|
||||
else if (FlowPercentage > 0.0f)
|
||||
{
|
||||
foreach (Pair<Vector2, ParticleEmitter> pumpInEmitter in pumpInEmitters)
|
||||
{
|
||||
pumpInEmitter.Second.Emit(deltaTime, item.WorldRect.Location.ToVector2() + pumpInEmitter.First * item.Scale, item.CurrentHull,
|
||||
velocityMultiplier: MathHelper.Lerp(0.5f, 1.0f, FlowPercentage / 100.0f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
||||
{
|
||||
GuiFrame.AddToGUIUpdateList();
|
||||
}
|
||||
powerIndicator.Selected = hasPower && IsActive;
|
||||
|
||||
public override void UpdateHUD(Character character)
|
||||
{
|
||||
GuiFrame.Update(1.0f / 60.0f);
|
||||
}
|
||||
if (!PlayerInput.LeftButtonHeld())
|
||||
{
|
||||
isActiveSlider.BarScroll += (IsActive ? -10.0f : 10.0f) * deltaTime;
|
||||
|
||||
float pumpSpeedScroll = (FlowPercentage + 100.0f) / 200.0f;
|
||||
if (Math.Abs(pumpSpeedScroll - pumpSpeedSlider.BarScroll) > 0.01f)
|
||||
{
|
||||
pumpSpeedSlider.BarScroll = pumpSpeedScroll;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientWrite(Lidgren.Network.NetBuffer msg, object[] extraData = null)
|
||||
{
|
||||
//flowpercentage can only be adjusted at 10% intervals -> no need for more accuracy than this
|
||||
|
||||
@@ -1,468 +0,0 @@
|
||||
using Barotrauma.Networking;
|
||||
using FarseerPhysics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Voronoi2;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class Radar : Powered, IServerSerializable, IClientSerializable
|
||||
{
|
||||
private GUITickBox isActiveTickBox;
|
||||
|
||||
private List<RadarBlip> radarBlips;
|
||||
|
||||
private static Color[] blipColorGradient =
|
||||
{
|
||||
Color.TransparentBlack,
|
||||
new Color(0, 50, 160),
|
||||
new Color(0, 133, 166),
|
||||
new Color(2, 159, 30),
|
||||
new Color(255, 255, 255)
|
||||
};
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
{
|
||||
GuiFrame.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
public override void UpdateHUD(Character character)
|
||||
{
|
||||
GuiFrame.Update((float)Timing.Step);
|
||||
|
||||
for (int i = radarBlips.Count - 1; i >= 0; i--)
|
||||
{
|
||||
radarBlips[i].FadeTimer -= (float)Timing.Step * 0.5f;
|
||||
if (radarBlips[i].FadeTimer <= 0.0f) radarBlips.RemoveAt(i);
|
||||
}
|
||||
|
||||
if (IsActive)
|
||||
{
|
||||
float pingRadius = displayRadius * pingState;
|
||||
Ping(item.WorldPosition, pingRadius, prevPingRadius, displayScale, range, 2.0f);
|
||||
prevPingRadius = pingRadius;
|
||||
return;
|
||||
}
|
||||
|
||||
float passivePingRadius = (float)Math.Sin(Timing.TotalTime * 10);
|
||||
if (passivePingRadius > 0.0f)
|
||||
{
|
||||
foreach (AITarget t in AITarget.List)
|
||||
{
|
||||
if (t.SoundRange <= 0.0f) continue;
|
||||
|
||||
if (Vector2.Distance(t.WorldPosition, item.WorldPosition) < t.SoundRange)
|
||||
{
|
||||
Ping(t.WorldPosition, t.SoundRange * passivePingRadius * 0.2f, t.SoundRange * prevPassivePingRadius * 0.2f, displayScale, t.SoundRange, 0.5f);
|
||||
|
||||
radarBlips.Add(new RadarBlip(t.WorldPosition, 1.0f, 1.0f));
|
||||
}
|
||||
}
|
||||
}
|
||||
prevPassivePingRadius = passivePingRadius;
|
||||
|
||||
}
|
||||
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
{
|
||||
GuiFrame.Draw(spriteBatch);
|
||||
|
||||
int radius = GuiFrame.Rect.Height / 2 - 10;
|
||||
DrawRadar(spriteBatch, new Rectangle((int)GuiFrame.Center.X - radius, (int)GuiFrame.Center.Y - radius, radius * 2, radius * 2));
|
||||
}
|
||||
|
||||
private void DrawRadar(SpriteBatch spriteBatch, Rectangle rect)
|
||||
{
|
||||
center = new Vector2(rect.X + rect.Width * 0.5f, rect.Center.Y);
|
||||
displayRadius = (rect.Width / 2.0f) * (1.0f - displayBorderSize);
|
||||
displayScale = displayRadius / range;
|
||||
|
||||
if (IsActive)
|
||||
{
|
||||
pingCircle.Draw(spriteBatch, center, Color.White * (1.0f - pingState), 0.0f, (displayRadius * 2 / pingCircle.size.X) * pingState);
|
||||
}
|
||||
|
||||
if (item.Submarine != null && !DetectSubmarineWalls)
|
||||
{
|
||||
float simScale = displayScale * Physics.DisplayToSimRation;
|
||||
|
||||
foreach (Submarine submarine in Submarine.Loaded)
|
||||
{
|
||||
if (submarine != item.Submarine && !submarine.DockedTo.Contains(item.Submarine)) continue;
|
||||
if (submarine.HullVertices == null) continue;
|
||||
|
||||
Vector2 offset = ConvertUnits.ToSimUnits(submarine.WorldPosition - item.WorldPosition);
|
||||
|
||||
for (int i = 0; i < submarine.HullVertices.Count; i++)
|
||||
{
|
||||
Vector2 start = (submarine.HullVertices[i] + offset) * simScale;
|
||||
start.Y = -start.Y;
|
||||
Vector2 end = (submarine.HullVertices[(i + 1) % submarine.HullVertices.Count] + offset) * simScale;
|
||||
end.Y = -end.Y;
|
||||
|
||||
GUI.DrawLine(spriteBatch, center + start, center + end, Color.LightBlue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (radarBlips.Count > 0)
|
||||
{
|
||||
spriteBatch.End();
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive);
|
||||
|
||||
foreach (RadarBlip radarBlip in radarBlips)
|
||||
{
|
||||
DrawBlip(spriteBatch, radarBlip, center, radarBlip.FadeTimer / 2.0f);
|
||||
}
|
||||
|
||||
spriteBatch.End();
|
||||
spriteBatch.Begin(SpriteSortMode.Immediate, null, null, null, GameMain.ScissorTestEnable);
|
||||
}
|
||||
|
||||
if (GameMain.DebugDraw)
|
||||
{
|
||||
GUI.DrawString(spriteBatch, rect.Location.ToVector2(), radarBlips.Count.ToString(), Color.White);
|
||||
}
|
||||
|
||||
if (screenOverlay != null)
|
||||
{
|
||||
screenOverlay.Draw(spriteBatch, center, 0.0f, rect.Width / screenOverlay.size.X);
|
||||
}
|
||||
|
||||
if (GameMain.GameSession == null) return;
|
||||
|
||||
DrawMarker(spriteBatch,
|
||||
GameMain.GameSession.StartLocation.Name,
|
||||
(Level.Loaded.StartPosition - item.WorldPosition), displayScale, center, (rect.Width * 0.5f));
|
||||
|
||||
DrawMarker(spriteBatch,
|
||||
GameMain.GameSession.EndLocation.Name,
|
||||
(Level.Loaded.EndPosition - item.WorldPosition), displayScale, center, (rect.Width * 0.5f));
|
||||
|
||||
if (GameMain.GameSession.Mission != null)
|
||||
{
|
||||
var mission = GameMain.GameSession.Mission;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(mission.RadarLabel) && mission.RadarPosition != Vector2.Zero)
|
||||
{
|
||||
DrawMarker(spriteBatch,
|
||||
mission.RadarLabel,
|
||||
mission.RadarPosition - item.WorldPosition, displayScale, center, (rect.Width * 0.55f));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Submarine sub in Submarine.Loaded)
|
||||
{
|
||||
if (!sub.OnRadar) continue;
|
||||
if (item.Submarine == sub || sub.DockedTo.Contains(item.Submarine)) continue;
|
||||
if (sub.WorldPosition.Y > Level.Loaded.Size.Y) continue;
|
||||
|
||||
DrawMarker(spriteBatch, sub.Name, sub.WorldPosition - item.WorldPosition, displayScale, center, (rect.Width * 0.45f));
|
||||
}
|
||||
|
||||
if (!GameMain.DebugDraw) return;
|
||||
|
||||
var steering = item.GetComponent<Steering>();
|
||||
if (steering == null || steering.SteeringPath == null) return;
|
||||
|
||||
Vector2 prevPos = Vector2.Zero;
|
||||
|
||||
foreach (WayPoint wp in steering.SteeringPath.Nodes)
|
||||
{
|
||||
Vector2 pos = (wp.Position - item.WorldPosition) * displayScale;
|
||||
if (pos.Length() > displayRadius) continue;
|
||||
|
||||
pos.Y = -pos.Y;
|
||||
pos += center;
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X - 3 / 2, (int)pos.Y - 3, 6, 6), (steering.SteeringPath.CurrentNode == wp) ? Color.LightGreen : Color.Green, false);
|
||||
|
||||
if (prevPos != Vector2.Zero)
|
||||
{
|
||||
GUI.DrawLine(spriteBatch, pos, prevPos, Color.Green);
|
||||
}
|
||||
|
||||
prevPos = pos;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void Ping(Vector2 pingSource, float pingRadius, float prevPingRadius, float displayScale, float range, float pingStrength = 1.0f)
|
||||
{
|
||||
//inside a hull -> only show the edges of the hull
|
||||
if (item.CurrentHull != null && DetectSubmarineWalls)
|
||||
{
|
||||
CreateBlipsForLine(
|
||||
new Vector2(item.CurrentHull.WorldRect.X, item.CurrentHull.WorldRect.Y),
|
||||
new Vector2(item.CurrentHull.WorldRect.Right, item.CurrentHull.WorldRect.Y),
|
||||
pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f);
|
||||
|
||||
CreateBlipsForLine(
|
||||
new Vector2(item.CurrentHull.WorldRect.X, item.CurrentHull.WorldRect.Y - item.CurrentHull.Rect.Height),
|
||||
new Vector2(item.CurrentHull.WorldRect.Right, item.CurrentHull.WorldRect.Y - item.CurrentHull.Rect.Height),
|
||||
pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f);
|
||||
|
||||
CreateBlipsForLine(
|
||||
new Vector2(item.CurrentHull.WorldRect.X, item.CurrentHull.WorldRect.Y),
|
||||
new Vector2(item.CurrentHull.WorldRect.X, item.CurrentHull.WorldRect.Y - item.CurrentHull.Rect.Height),
|
||||
pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f);
|
||||
|
||||
CreateBlipsForLine(
|
||||
new Vector2(item.CurrentHull.WorldRect.Right, item.CurrentHull.WorldRect.Y),
|
||||
new Vector2(item.CurrentHull.WorldRect.Right, item.CurrentHull.WorldRect.Y - item.CurrentHull.Rect.Height),
|
||||
pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (Submarine submarine in Submarine.Loaded)
|
||||
{
|
||||
if (item.Submarine == submarine && !DetectSubmarineWalls) continue;
|
||||
if (item.Submarine != null && item.Submarine.DockedTo.Contains(submarine)) continue;
|
||||
if (submarine.HullVertices == null) continue;
|
||||
|
||||
for (int i = 0; i < submarine.HullVertices.Count; i++)
|
||||
{
|
||||
Vector2 start = ConvertUnits.ToDisplayUnits(submarine.HullVertices[i]);
|
||||
Vector2 end = ConvertUnits.ToDisplayUnits(submarine.HullVertices[(i + 1) % submarine.HullVertices.Count]);
|
||||
|
||||
if (item.Submarine == submarine)
|
||||
{
|
||||
start += Rand.Vector(500.0f);
|
||||
end += Rand.Vector(500.0f);
|
||||
}
|
||||
|
||||
CreateBlipsForLine(
|
||||
start + submarine.WorldPosition,
|
||||
end + submarine.WorldPosition,
|
||||
pingRadius, prevPingRadius,
|
||||
200.0f, 2.0f, range, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
if (Level.Loaded != null && (item.CurrentHull == null || !DetectSubmarineWalls))
|
||||
{
|
||||
if (Level.Loaded.Size.Y - pingSource.Y < range)
|
||||
{
|
||||
CreateBlipsForLine(
|
||||
new Vector2(pingSource.X - range, Level.Loaded.Size.Y),
|
||||
new Vector2(pingSource.X + range, Level.Loaded.Size.Y),
|
||||
pingRadius, prevPingRadius,
|
||||
250.0f, 150.0f, range, pingStrength);
|
||||
}
|
||||
|
||||
List<VoronoiCell> cells = Level.Loaded.GetCells(pingSource, 7);
|
||||
foreach (VoronoiCell cell in cells)
|
||||
{
|
||||
foreach (GraphEdge edge in cell.edges)
|
||||
{
|
||||
if (!edge.isSolid) continue;
|
||||
float cellDot = Vector2.Dot(cell.Center - pingSource, (edge.Center + cell.Translation) - cell.Center);
|
||||
if (cellDot > 0) continue;
|
||||
|
||||
float facingDot = Vector2.Dot(
|
||||
Vector2.Normalize(edge.point1 - edge.point2),
|
||||
Vector2.Normalize(cell.Center - pingSource));
|
||||
|
||||
CreateBlipsForLine(
|
||||
edge.point1 + cell.Translation,
|
||||
edge.point2 + cell.Translation,
|
||||
pingRadius, prevPingRadius,
|
||||
350.0f, 3.0f * (Math.Abs(facingDot) + 1.0f), range, pingStrength);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (RuinGeneration.Ruin ruin in Level.Loaded.Ruins)
|
||||
{
|
||||
if (!MathUtils.CircleIntersectsRectangle(pingSource, range, ruin.Area)) continue;
|
||||
|
||||
foreach (var ruinShape in ruin.RuinShapes)
|
||||
{
|
||||
foreach (RuinGeneration.Line wall in ruinShape.Walls)
|
||||
{
|
||||
float cellDot = Vector2.Dot(
|
||||
Vector2.Normalize(ruinShape.Center - pingSource),
|
||||
Vector2.Normalize((wall.A + wall.B) / 2.0f - ruinShape.Center));
|
||||
if (cellDot > 0) continue;
|
||||
|
||||
CreateBlipsForLine(
|
||||
wall.A, wall.B,
|
||||
pingRadius, prevPingRadius,
|
||||
100.0f, 1000.0f, range, pingStrength);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Character c in Character.CharacterList)
|
||||
{
|
||||
if (c.AnimController.CurrentHull != null || !c.Enabled) continue;
|
||||
if (DetectSubmarineWalls && c.AnimController.CurrentHull == null && item.CurrentHull != null) continue;
|
||||
|
||||
foreach (Limb limb in c.AnimController.Limbs)
|
||||
{
|
||||
float pointDist = (limb.WorldPosition - pingSource).Length() * displayScale;
|
||||
|
||||
if (limb.SimPosition == Vector2.Zero || pointDist > displayRadius) continue;
|
||||
|
||||
if (pointDist > prevPingRadius && pointDist < pingRadius)
|
||||
{
|
||||
var blip = new RadarBlip(
|
||||
limb.WorldPosition + Rand.Vector(limb.Mass / 10.0f),
|
||||
MathHelper.Clamp(limb.Mass, 0.1f, pingStrength),
|
||||
MathHelper.Clamp(limb.Mass * 0.1f, 0.1f, 2.0f));
|
||||
radarBlips.Add(blip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateBlipsForLine(Vector2 point1, Vector2 point2, float pingRadius, float prevPingRadius,
|
||||
float lineStep, float zStep, float range, float pingStrength)
|
||||
{
|
||||
float length = (point1 - point2).Length();
|
||||
|
||||
Vector2 lineDir = (point2 - point1) / length;
|
||||
|
||||
range *= displayScale;
|
||||
|
||||
for (float x = 0; x < length; x += lineStep * Rand.Range(0.8f, 1.2f))
|
||||
{
|
||||
Vector2 point = point1 + lineDir * x;
|
||||
//point += cell.Translation;
|
||||
|
||||
float pointDist = Vector2.Distance(item.WorldPosition, point) * displayScale;
|
||||
|
||||
if (pointDist > displayRadius) continue;
|
||||
if (pointDist < prevPingRadius || pointDist > pingRadius) continue;
|
||||
|
||||
float alpha = pingStrength * Rand.Range(1.5f, 2.0f);
|
||||
for (float z = 0; z < displayRadius - pointDist * displayScale; z += zStep)
|
||||
{
|
||||
Vector2 pos = point + Rand.Vector(150.0f) + Vector2.Normalize(point - item.WorldPosition) * z / displayScale;
|
||||
float fadeTimer = alpha * (1.0f - pointDist / range);
|
||||
|
||||
int minDist = 200;
|
||||
radarBlips.RemoveAll(b => b.FadeTimer < fadeTimer && Math.Abs(pos.X - b.Position.X) < minDist && Math.Abs(pos.Y - b.Position.Y) < minDist);
|
||||
|
||||
var blip = new RadarBlip(pos, fadeTimer, 1.0f + ((pointDist+z) / displayRadius));
|
||||
|
||||
radarBlips.Add(blip);
|
||||
zStep += 0.5f;
|
||||
|
||||
if (z == 0)
|
||||
{
|
||||
alpha = Math.Min(alpha - 0.5f, 1.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
alpha -= 0.1f;
|
||||
}
|
||||
|
||||
if (alpha < 0) break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawBlip(SpriteBatch spriteBatch, RadarBlip blip, Vector2 center, float strength)
|
||||
{
|
||||
strength = MathHelper.Clamp(strength, 0.0f, 1.0f);
|
||||
|
||||
float scaledT = strength * (blipColorGradient.Length - 1);
|
||||
Color color = Color.Lerp(blipColorGradient[(int)scaledT], blipColorGradient[(int)Math.Min(scaledT + 1, blipColorGradient.Length - 1)], (scaledT - (int)scaledT));
|
||||
|
||||
Vector2 pos = (blip.Position - item.WorldPosition) * displayScale;
|
||||
pos.Y = -pos.Y;
|
||||
|
||||
float posDist = pos.Length();
|
||||
if (posDist > displayRadius)
|
||||
{
|
||||
blip.FadeTimer = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
if (radarBlip == null)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, center + pos, Vector2.One * 4, Color.Magenta, true);
|
||||
return;
|
||||
}
|
||||
|
||||
Vector2 dir = pos / posDist;
|
||||
|
||||
Vector2 normal = new Vector2(dir.Y, -dir.X);
|
||||
float scale = (strength + 3.0f) * blip.Scale;
|
||||
|
||||
radarBlip.Draw(spriteBatch, center + pos, color, radarBlip.Origin, MathUtils.VectorToAngle(pos),
|
||||
new Vector2(scale * 0.5f, scale) * 0.04f, SpriteEffects.None, 0);
|
||||
|
||||
pos += Rand.Range(0.0f, 1.0f) * dir + Rand.Range(-scale, scale) * normal;
|
||||
|
||||
radarBlip.Draw(spriteBatch, center + pos, color * 0.5f, radarBlip.Origin, 0, scale * 0.08f, SpriteEffects.None, 0);
|
||||
}
|
||||
|
||||
private void DrawMarker(SpriteBatch spriteBatch, string label, Vector2 position, float scale, Vector2 center, float radius)
|
||||
{
|
||||
float dist = position.Length();
|
||||
|
||||
position *= scale;
|
||||
position.Y = -position.Y;
|
||||
|
||||
float textAlpha = MathHelper.Clamp(1.5f - dist / 50000.0f, 0.5f, 1.0f);
|
||||
|
||||
Vector2 dir = Vector2.Normalize(position);
|
||||
|
||||
Vector2 markerPos = (dist * scale > radius) ? dir * radius : position;
|
||||
markerPos += center;
|
||||
|
||||
markerPos.X = (int)markerPos.X;
|
||||
markerPos.Y = (int)markerPos.Y;
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)markerPos.X, (int)markerPos.Y, 5, 5), Color.LightBlue);
|
||||
|
||||
if (dir.X < 0.0f) markerPos.X -= GUI.SmallFont.MeasureString(label).X + 10;
|
||||
|
||||
string wrappedLabel = ToolBox.WrapText(label, 150, GUI.SmallFont);
|
||||
wrappedLabel += "\n" + ((int)(dist * Physics.DisplayToRealWorldRatio) + " m");
|
||||
|
||||
GUI.DrawString(spriteBatch,
|
||||
new Vector2(markerPos.X + 10, markerPos.Y),
|
||||
wrappedLabel,
|
||||
Color.LightBlue * textAlpha, Color.Black * textAlpha * 0.5f,
|
||||
2, GUI.SmallFont);
|
||||
}
|
||||
|
||||
public void ClientWrite(Lidgren.Network.NetBuffer msg, object[] extraData = null)
|
||||
{
|
||||
msg.Write(IsActive);
|
||||
}
|
||||
|
||||
public void ClientRead(ServerNetObject type, Lidgren.Network.NetBuffer msg, float sendingTime)
|
||||
{
|
||||
if (correctionTimer > 0.0f)
|
||||
{
|
||||
StartDelayedCorrection(type, msg.ExtractBits(1), sendingTime);
|
||||
return;
|
||||
}
|
||||
|
||||
IsActive = msg.ReadBoolean();
|
||||
isActiveTickBox.Selected = IsActive;
|
||||
}
|
||||
}
|
||||
|
||||
class RadarBlip
|
||||
{
|
||||
public float FadeTimer;
|
||||
public Vector2 Position;
|
||||
public float Scale;
|
||||
|
||||
public RadarBlip(Vector2 pos, float fadeTimer, float scale)
|
||||
{
|
||||
Position = pos;
|
||||
FadeTimer = Math.Max(fadeTimer, 0.0f);
|
||||
Scale = scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,200 +4,458 @@ using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class Reactor : Powered, IDrawableComponent, IServerSerializable, IClientSerializable
|
||||
partial class Reactor : Powered, IServerSerializable, IClientSerializable
|
||||
{
|
||||
private GUITickBox autoTempTickBox;
|
||||
|
||||
private GUIScrollBar autoTempSlider;
|
||||
private GUIScrollBar onOffSwitch;
|
||||
|
||||
private const int GraphSize = 25;
|
||||
private float graphTimer;
|
||||
private int updateGraphInterval = 500;
|
||||
|
||||
private Sprite fissionRateMeter, turbineOutputMeter;
|
||||
private Sprite meterPointer;
|
||||
private Sprite sectorSprite;
|
||||
|
||||
private float[] fissionRateGraph = new float[GraphSize];
|
||||
private float[] coolingRateGraph = new float[GraphSize];
|
||||
private float[] tempGraph = new float[GraphSize];
|
||||
private Sprite tempMeterFrame, tempMeterBar;
|
||||
private Sprite tempRangeIndicator;
|
||||
|
||||
private Sprite graphLine;
|
||||
|
||||
private GUIScrollBar fissionRateScrollBar;
|
||||
private GUIScrollBar turbineOutputScrollBar;
|
||||
|
||||
private float[] outputGraph = new float[GraphSize];
|
||||
private float[] loadGraph = new float[GraphSize];
|
||||
|
||||
private GUITickBox criticalHeatWarning;
|
||||
private GUITickBox lowTemperatureWarning;
|
||||
private GUITickBox criticalOutputWarning;
|
||||
|
||||
partial void InitProjSpecific()
|
||||
private GUIFrame inventoryContainer;
|
||||
|
||||
private GUIComponent leftHUDColumn;
|
||||
|
||||
private Dictionary<string, GUIButton> warningButtons = new Dictionary<string, GUIButton>();
|
||||
|
||||
private static string[] warningTexts = new string[]
|
||||
{
|
||||
var button = new GUIButton(new Rectangle(410, 70, 40, 40), "-", "", GuiFrame);
|
||||
button.OnPressed = () =>
|
||||
{
|
||||
lastUser = Character.Controlled;
|
||||
if (nextServerLogWriteTime == null)
|
||||
{
|
||||
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
|
||||
}
|
||||
unsentChanges = true;
|
||||
ShutDownTemp -= 100.0f;
|
||||
"ReactorWarningLowTemp","ReactorWarningOverheating",
|
||||
"ReactorWarningLowOutput", "ReactorWarningHighOutput",
|
||||
"ReactorWarningLowFuel", "ReactorWarningFuelOut",
|
||||
"ReactorWarningMeltdown","ReactorWarningSCRAM"
|
||||
};
|
||||
|
||||
return false;
|
||||
partial void InitProjSpecific(XElement element)
|
||||
{
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "fissionratemeter":
|
||||
fissionRateMeter = new Sprite(subElement);
|
||||
break;
|
||||
case "turbineoutputmeter":
|
||||
turbineOutputMeter = new Sprite(subElement);
|
||||
break;
|
||||
case "meterpointer":
|
||||
meterPointer = new Sprite(subElement);
|
||||
break;
|
||||
case "sectorsprite":
|
||||
sectorSprite = new Sprite(subElement);
|
||||
break;
|
||||
case "tempmeterframe":
|
||||
tempMeterFrame = new Sprite(subElement);
|
||||
break;
|
||||
case "tempmeterbar":
|
||||
tempMeterBar = new Sprite(subElement);
|
||||
break;
|
||||
case "temprangeindicator":
|
||||
tempRangeIndicator = new Sprite(subElement);
|
||||
break;
|
||||
case "graphline":
|
||||
graphLine = new Sprite(subElement);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.85f), GuiFrame.RectTransform, Anchor.Center), isHorizontal: true)
|
||||
{
|
||||
RelativeSpacing = 0.015f,
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
GUIFrame columnLeft = new GUIFrame(new RectTransform(new Vector2(0.2f, 1.0f), paddedFrame.RectTransform), style: null);
|
||||
leftHUDColumn = columnLeft;
|
||||
GUIFrame columnMid = new GUIFrame(new RectTransform(new Vector2(0.45f, 1.0f), paddedFrame.RectTransform), style: null);
|
||||
GUIFrame columnRight = new GUIFrame(new RectTransform(new Vector2(0.35f, 1.0f), paddedFrame.RectTransform), style: null);
|
||||
|
||||
//----------------------------------------------------------
|
||||
//left column
|
||||
//----------------------------------------------------------
|
||||
|
||||
int buttonsPerRow = 2;
|
||||
int spacing = 5;
|
||||
int buttonWidth = columnLeft.Rect.Width / buttonsPerRow - (spacing * (buttonsPerRow - 1));
|
||||
int buttonHeight = (int)(columnLeft.Rect.Height * 0.5f) / 4;
|
||||
for (int i = 0; i < warningTexts.Length; i++)
|
||||
{
|
||||
var warningBtn = new GUIButton(new RectTransform(new Point(buttonWidth, buttonHeight), columnLeft.RectTransform)
|
||||
{ AbsoluteOffset = new Point((i % buttonsPerRow) * (buttonWidth + spacing), (int)Math.Floor(i / (float)buttonsPerRow) * (buttonHeight + spacing)) },
|
||||
TextManager.Get(warningTexts[i]), style: "IndicatorButton");
|
||||
|
||||
var btnText = warningBtn.GetChild<GUITextBlock>();
|
||||
btnText.Font = GUI.SmallFont;
|
||||
btnText.Wrap = true;
|
||||
btnText.SetTextPos();
|
||||
warningButtons.Add(warningTexts[i], warningBtn);
|
||||
}
|
||||
|
||||
inventoryContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.45f), columnLeft.RectTransform, Anchor.BottomLeft), style: null);
|
||||
|
||||
//----------------------------------------------------------
|
||||
//mid column
|
||||
//----------------------------------------------------------
|
||||
|
||||
criticalHeatWarning = new GUITickBox(new RectTransform(new Point(30, 30), columnMid.RectTransform),
|
||||
TextManager.Get("ReactorWarningCriticalTemp"), font: GUI.SmallFont, style: "IndicatorLightRed")
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
lowTemperatureWarning = new GUITickBox(new RectTransform(new Point(30, 30), columnMid.RectTransform) { RelativeOffset = new Vector2(0.3f, 0.0f) },
|
||||
TextManager.Get("ReactorWarningCriticalLowTemp"), font: GUI.SmallFont, style: "IndicatorLightRed")
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
criticalOutputWarning = new GUITickBox(new RectTransform(new Point(30, 30), columnMid.RectTransform) { RelativeOffset = new Vector2(0.75f, 0.0f) },
|
||||
TextManager.Get("ReactorWarningCriticalOutput"), font: GUI.SmallFont, style: "IndicatorLightRed")
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.05f), columnMid.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.25f) },
|
||||
TextManager.Get("ReactorFissionRate"));
|
||||
new GUICustomComponent(new RectTransform(new Vector2(0.5f, 0.5f), columnMid.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.3f) },
|
||||
DrawFissionRateMeter, null)
|
||||
{
|
||||
ToolTip = TextManager.Get("ReactorTipFissionRate")
|
||||
};
|
||||
|
||||
button = new GUIButton(new Rectangle(460, 70, 40, 40), "+", "", GuiFrame);
|
||||
button.OnPressed = () =>
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.05f), columnMid.RectTransform, Anchor.TopRight) { RelativeOffset = new Vector2(0.0f, 0.25f) },
|
||||
TextManager.Get("ReactorTurbineOutput"));
|
||||
new GUICustomComponent(new RectTransform(new Vector2(0.5f, 0.5f), columnMid.RectTransform, Anchor.TopRight) { RelativeOffset = new Vector2(0.0f, 0.3f) },
|
||||
DrawTurbineOutputMeter, null)
|
||||
{
|
||||
lastUser = Character.Controlled;
|
||||
if (nextServerLogWriteTime == null)
|
||||
{
|
||||
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
|
||||
}
|
||||
unsentChanges = true;
|
||||
ShutDownTemp += 100.0f;
|
||||
|
||||
return false;
|
||||
ToolTip = TextManager.Get("ReactorTipTurbineOutput")
|
||||
};
|
||||
|
||||
autoTempTickBox = new GUITickBox(new Rectangle(410, 170, 20, 20), TextManager.Get("ReactorAutoTemp"), Alignment.TopLeft, GuiFrame);
|
||||
autoTempTickBox.OnSelected = ToggleAutoTemp;
|
||||
|
||||
button = new GUIButton(new Rectangle(210, 290, 40, 40), "+", "", GuiFrame);
|
||||
button.OnPressed = () =>
|
||||
new GUITextBlock(new RectTransform(new Point(0, 20), columnMid.RectTransform, Anchor.BottomLeft) { AbsoluteOffset = new Point(0, 90) },
|
||||
TextManager.Get("ReactorFissionRate"));
|
||||
fissionRateScrollBar = new GUIScrollBar(new RectTransform(new Point(columnMid.Rect.Width, 30), columnMid.RectTransform, Anchor.BottomCenter) { AbsoluteOffset = new Point(0, 60) },
|
||||
style: "GUISlider", barSize: 0.1f)
|
||||
{
|
||||
lastUser = Character.Controlled;
|
||||
if (nextServerLogWriteTime == null)
|
||||
OnMoved = (GUIScrollBar bar, float scrollAmount) =>
|
||||
{
|
||||
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
|
||||
}
|
||||
unsentChanges = true;
|
||||
FissionRate += 1.0f;
|
||||
LastUser = Character.Controlled;
|
||||
if (nextServerLogWriteTime == null)
|
||||
{
|
||||
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
|
||||
}
|
||||
unsentChanges = true;
|
||||
targetFissionRate = scrollAmount * 100.0f;
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
button = new GUIButton(new Rectangle(210, 340, 40, 40), "-", "", GuiFrame);
|
||||
button.OnPressed = () =>
|
||||
new GUITextBlock(new RectTransform(new Point(0, 20), columnMid.RectTransform, Anchor.BottomLeft) { AbsoluteOffset = new Point(0, 30) },
|
||||
TextManager.Get("ReactorTurbineOutput"));
|
||||
turbineOutputScrollBar = new GUIScrollBar(new RectTransform(new Point(columnMid.Rect.Width, 30), columnMid.RectTransform, Anchor.BottomCenter),
|
||||
style: "GUISlider", barSize: 0.1f, isHorizontal: true)
|
||||
{
|
||||
lastUser = Character.Controlled;
|
||||
if (nextServerLogWriteTime == null)
|
||||
OnMoved = (GUIScrollBar bar, float scrollAmount) =>
|
||||
{
|
||||
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
|
||||
}
|
||||
unsentChanges = true;
|
||||
FissionRate -= 1.0f;
|
||||
LastUser = Character.Controlled;
|
||||
if (nextServerLogWriteTime == null)
|
||||
{
|
||||
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
|
||||
}
|
||||
unsentChanges = true;
|
||||
targetTurbineOutput = scrollAmount * 100.0f;
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
button = new GUIButton(new Rectangle(500, 290, 40, 40), "+", "", GuiFrame);
|
||||
button.OnPressed = () =>
|
||||
//----------------------------------------------------------
|
||||
//right column
|
||||
//----------------------------------------------------------
|
||||
|
||||
new GUITextBlock(new RectTransform(new Point(100, 20), columnRight.RectTransform), TextManager.Get("ReactorAutoTemp"))
|
||||
{
|
||||
lastUser = Character.Controlled;
|
||||
if (nextServerLogWriteTime == null)
|
||||
{
|
||||
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
|
||||
}
|
||||
unsentChanges = true;
|
||||
CoolingRate += 1.0f;
|
||||
|
||||
return false;
|
||||
ToolTip = TextManager.Get("ReactorTipAutoTemp")
|
||||
};
|
||||
|
||||
button = new GUIButton(new Rectangle(500, 340, 40, 40), "-", "", GuiFrame);
|
||||
button.OnPressed = () =>
|
||||
autoTempSlider = new GUIScrollBar(new RectTransform(new Point(100, 30), columnRight.RectTransform) { AbsoluteOffset = new Point(0, 30) },
|
||||
barSize: 0.5f, style: "OnOffSlider")
|
||||
{
|
||||
lastUser = Character.Controlled;
|
||||
if (nextServerLogWriteTime == null)
|
||||
ToolTip = TextManager.Get("ReactorTipAutoTemp"),
|
||||
IsBooleanSwitch = true,
|
||||
BarScroll = 1.0f,
|
||||
OnMoved = (scrollBar, scrollAmount) =>
|
||||
{
|
||||
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
|
||||
LastUser = Character.Controlled;
|
||||
if (nextServerLogWriteTime == null)
|
||||
{
|
||||
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
|
||||
}
|
||||
unsentChanges = true;
|
||||
return true;
|
||||
}
|
||||
unsentChanges = true;
|
||||
CoolingRate -= 1.0f;
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
onOffSwitch = new GUIScrollBar(new RectTransform(new Point(50, 80), columnRight.RectTransform, Anchor.TopRight),
|
||||
barSize: 0.2f, style: "OnOffLever")
|
||||
{
|
||||
IsBooleanSwitch = true,
|
||||
MinValue = 0.25f,
|
||||
MaxValue = 0.75f,
|
||||
OnMoved = (scrollBar, scrollAmount) =>
|
||||
{
|
||||
LastUser = Character.Controlled;
|
||||
if (nextServerLogWriteTime == null)
|
||||
{
|
||||
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
|
||||
}
|
||||
unsentChanges = true;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
var lever = onOffSwitch.GetChild<GUIButton>();
|
||||
lever.RectTransform.NonScaledSize = new Point(lever.Rect.Width + 30, lever.Rect.Height);
|
||||
|
||||
var graphArea = new GUICustomComponent(new RectTransform(new Vector2(1.0f, 0.5f), columnRight.RectTransform, Anchor.BottomCenter) { AbsoluteOffset = new Point(0, 30) },
|
||||
DrawGraph, null);
|
||||
|
||||
var loadText = new GUITextBlock(new RectTransform(new Point(100, 30), graphArea.RectTransform, Anchor.TopLeft, Pivot.BottomLeft),
|
||||
"Load", textColor: Color.LightBlue, textAlignment: Alignment.CenterLeft)
|
||||
{
|
||||
ToolTip = TextManager.Get("ReactorTipLoad")
|
||||
};
|
||||
string loadStr = TextManager.Get("ReactorLoad");
|
||||
loadText.TextGetter += () => { return loadStr.Replace("[kw]", ((int)load).ToString()); };
|
||||
|
||||
var outputText = new GUITextBlock(new RectTransform(new Point(100, 30), graphArea.RectTransform, Anchor.BottomLeft, Pivot.TopLeft),
|
||||
"Output", textColor: Color.LightGreen, textAlignment: Alignment.CenterLeft)
|
||||
{
|
||||
ToolTip = TextManager.Get("ReactorTipPower")
|
||||
};
|
||||
string outputStr = TextManager.Get("ReactorOutput");
|
||||
outputText.TextGetter += () => { return outputStr.Replace("[kw]", ((int)-currPowerConsumption).ToString()); };
|
||||
}
|
||||
|
||||
public override void OnItemLoaded()
|
||||
{
|
||||
turbineOutputScrollBar.BarScroll = targetTurbineOutput / 100.0f;
|
||||
fissionRateScrollBar.BarScroll = targetFissionRate / 100.0f;
|
||||
var itemContainer = item.GetComponent<ItemContainer>();
|
||||
if (itemContainer != null)
|
||||
{
|
||||
itemContainer.AllowUIOverlap = true;
|
||||
itemContainer.Inventory.RectTransform = inventoryContainer.RectTransform;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawGraph(SpriteBatch spriteBatch, GUICustomComponent container)
|
||||
{
|
||||
Rectangle graphArea = new Rectangle(container.Rect.X + 30, container.Rect.Y, container.Rect.Width - 30, container.Rect.Height);
|
||||
|
||||
float maxLoad = loadGraph.Max();
|
||||
|
||||
float xOffset = graphTimer / updateGraphInterval;
|
||||
DrawGraph(outputGraph, spriteBatch,
|
||||
graphArea, Math.Max(10000.0f, maxLoad), xOffset, Color.LightGreen);
|
||||
|
||||
DrawGraph(loadGraph, spriteBatch,
|
||||
graphArea, Math.Max(10000.0f, maxLoad), xOffset, Color.LightBlue);
|
||||
|
||||
tempMeterFrame.Draw(spriteBatch, new Vector2(graphArea.X - 30, graphArea.Y), Color.White, Vector2.Zero, 0.0f, new Vector2(1.0f, graphArea.Height / tempMeterFrame.size.Y));
|
||||
float tempFill = temperature / 100.0f;
|
||||
|
||||
int barPadding = 5;
|
||||
Vector2 meterBarPos = new Vector2(graphArea.X - 30 + tempMeterFrame.size.X / 2, graphArea.Bottom - tempMeterBar.size.Y);
|
||||
while (meterBarPos.Y > graphArea.Bottom - graphArea.Height * tempFill)
|
||||
{
|
||||
float tempRatio = 1.0f - ((meterBarPos.Y - graphArea.Y) / graphArea.Height);
|
||||
Color color = tempRatio < 0.5f ?
|
||||
Color.Lerp(Color.Green, Color.Orange, tempRatio * 2.0f) :
|
||||
Color.Lerp(Color.Orange, Color.Red, (tempRatio - 0.5f) * 2.0f);
|
||||
|
||||
tempMeterBar.Draw(spriteBatch, meterBarPos, color);
|
||||
meterBarPos.Y -= (tempMeterBar.size.Y + barPadding);
|
||||
}
|
||||
|
||||
if (temperature > optimalTemperature.Y)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
new Vector2(graphArea.X - 30, graphArea.Y),
|
||||
new Vector2(tempMeterFrame.SourceRect.Width, (graphArea.Bottom - graphArea.Height * optimalTemperature.Y / 100.0f) - graphArea.Y),
|
||||
Color.Red * (float)Math.Sin(Timing.TotalTime * 5.0f) * 0.7f, isFilled: true);
|
||||
}
|
||||
if (temperature < optimalTemperature.X)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
new Vector2(graphArea.X - 30, graphArea.Bottom - graphArea.Height * optimalTemperature.X / 100.0f),
|
||||
new Vector2(tempMeterFrame.SourceRect.Width, graphArea.Bottom - (graphArea.Bottom - graphArea.Height * optimalTemperature.X / 100.0f)),
|
||||
Color.Red * (float)Math.Sin(Timing.TotalTime * 5.0f) * 0.7f, isFilled: true);
|
||||
}
|
||||
|
||||
tempRangeIndicator.Draw(spriteBatch, new Vector2(meterBarPos.X, graphArea.Bottom - graphArea.Height * optimalTemperature.X / 100.0f));
|
||||
tempRangeIndicator.Draw(spriteBatch, new Vector2(meterBarPos.X, graphArea.Bottom - graphArea.Height * optimalTemperature.Y / 100.0f));
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void UpdateGraph(float deltaTime)
|
||||
{
|
||||
graphTimer += deltaTime * 1000.0f;
|
||||
|
||||
if (graphTimer > updateGraphInterval)
|
||||
{
|
||||
UpdateGraph(fissionRateGraph, fissionRate);
|
||||
UpdateGraph(coolingRateGraph, coolingRate);
|
||||
UpdateGraph(tempGraph, temperature);
|
||||
|
||||
UpdateGraph(outputGraph, -currPowerConsumption);
|
||||
UpdateGraph(loadGraph, load);
|
||||
|
||||
graphTimer = 0.0f;
|
||||
}
|
||||
|
||||
if (autoTemp)
|
||||
{
|
||||
fissionRateScrollBar.BarScroll = FissionRate / 100.0f;
|
||||
turbineOutputScrollBar.BarScroll = TurbineOutput / 100.0f;
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing = false)
|
||||
private void DrawFissionRateMeter(SpriteBatch spriteBatch, GUICustomComponent container)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
new Vector2(item.Rect.X + item.Rect.Width / 2 - 6, -item.Rect.Y + 29),
|
||||
new Vector2(12, 42), Color.Black);
|
||||
Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle;
|
||||
spriteBatch.End();
|
||||
spriteBatch.GraphicsDevice.ScissorRectangle = container.Rect;
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, rasterizerState: GameMain.ScissorTestEnable);
|
||||
|
||||
if (temperature > 0)
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
new Vector2(item.Rect.X + item.Rect.Width / 2 - 5, -item.Rect.Y + 30 + (40.0f * (1.0f - temperature / 10000.0f))),
|
||||
new Vector2(10, 40 * (temperature / 10000.0f)), new Color(temperature / 10000.0f, 1.0f - (temperature / 10000.0f), 0.0f, 1.0f), true);
|
||||
DrawMeter(spriteBatch, container.Rect,
|
||||
fissionRateMeter, FissionRate, new Vector2(0.0f, 100.0f), optimalFissionRate, allowedFissionRate);
|
||||
|
||||
spriteBatch.End();
|
||||
spriteBatch.GraphicsDevice.ScissorRectangle = prevScissorRect;
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred);
|
||||
}
|
||||
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
private void DrawTurbineOutputMeter(SpriteBatch spriteBatch, GUICustomComponent container)
|
||||
{
|
||||
DrawMeter(spriteBatch, container.Rect,
|
||||
turbineOutputMeter, TurbineOutput, new Vector2(0.0f, 100.0f), optimalTurbineOutput, allowedTurbineOutput);
|
||||
}
|
||||
|
||||
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
||||
{
|
||||
IsActive = true;
|
||||
|
||||
int x = GuiFrame.Rect.X;
|
||||
int y = GuiFrame.Rect.Y;
|
||||
|
||||
GuiFrame.Draw(spriteBatch);
|
||||
|
||||
float xOffset = graphTimer / updateGraphInterval;
|
||||
|
||||
GUI.Font.DrawString(spriteBatch, TextManager.Get("ReactorOutput") + ": " + (int)temperature + " kW",
|
||||
new Vector2(x + 450, y + 30), Color.Red);
|
||||
GUI.Font.DrawString(spriteBatch, TextManager.Get("ReactorGridLoad") + ": " + (int)load + " kW",
|
||||
new Vector2(x + 600, y + 30), Color.Yellow);
|
||||
bool lightOn = Timing.TotalTime % 0.5f < 0.25f && onOffSwitch.BarScroll < 0.5f;
|
||||
|
||||
float maxLoad = 0.0f;
|
||||
foreach (float loadVal in loadGraph)
|
||||
fissionRateScrollBar.Enabled = !autoTemp;
|
||||
turbineOutputScrollBar.Enabled = !autoTemp;
|
||||
|
||||
criticalHeatWarning.Selected = temperature > allowedTemperature.Y && lightOn;
|
||||
lowTemperatureWarning.Selected = temperature < allowedTemperature.X && lightOn;
|
||||
criticalOutputWarning.Selected = -currPowerConsumption > load * 1.5f && lightOn;
|
||||
|
||||
warningButtons["ReactorWarningOverheating"].Selected = temperature > optimalTemperature.Y && lightOn;
|
||||
warningButtons["ReactorWarningHighOutput"].Selected = -currPowerConsumption > load * 1.1f && lightOn;
|
||||
warningButtons["ReactorWarningLowTemp"].Selected = temperature < optimalTemperature.X && lightOn;
|
||||
warningButtons["ReactorWarningLowOutput"].Selected = -currPowerConsumption < load * 0.9f && lightOn;
|
||||
warningButtons["ReactorWarningFuelOut"].Selected = prevAvailableFuel < fissionRate * 0.01f && lightOn;
|
||||
warningButtons["ReactorWarningLowFuel"].Selected = prevAvailableFuel < fissionRate && lightOn;
|
||||
warningButtons["ReactorWarningMeltdown"].Selected = meltDownTimer > MeltdownDelay * 0.5f || item.Condition == 0.0f && lightOn;
|
||||
warningButtons["ReactorWarningSCRAM"].Selected = temperature > 0.1f && onOffSwitch.BarScroll > 0.5f;
|
||||
|
||||
AutoTemp = autoTempSlider.BarScroll < 0.5f;
|
||||
shutDown = onOffSwitch.BarScroll > 0.5f;
|
||||
|
||||
if (shutDown)
|
||||
{
|
||||
maxLoad = Math.Max(maxLoad, loadVal);
|
||||
}
|
||||
|
||||
DrawGraph(tempGraph, spriteBatch,
|
||||
new Rectangle(x + 30, y + 30, 400, 250), Math.Max(10000.0f, maxLoad), xOffset, Color.Red);
|
||||
|
||||
DrawGraph(loadGraph, spriteBatch,
|
||||
new Rectangle(x + 30, y + 30, 400, 250), Math.Max(10000.0f, maxLoad), xOffset, Color.Yellow);
|
||||
|
||||
GUI.Font.DrawString(spriteBatch, TextManager.Get("ReactorShutdownTemp") + ": " + (int)shutDownTemp, new Vector2(x + 450, y + 80), Color.White);
|
||||
|
||||
y += 300;
|
||||
|
||||
GUI.Font.DrawString(spriteBatch, TextManager.Get("ReactorFissionRate") + ": " + (int)fissionRate + " %", new Vector2(x + 30, y), Color.White);
|
||||
DrawGraph(fissionRateGraph, spriteBatch,
|
||||
new Rectangle(x + 30, y + 30, 200, 100), 100.0f, xOffset, Color.Orange);
|
||||
|
||||
|
||||
GUI.Font.DrawString(spriteBatch, TextManager.Get("ReactorCoolingRate") + ": " + (int)coolingRate + " %", new Vector2(x + 320, y), Color.White);
|
||||
DrawGraph(coolingRateGraph, spriteBatch,
|
||||
new Rectangle(x + 320, y + 30, 200, 100), 100.0f, xOffset, Color.LightBlue);
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
{
|
||||
GuiFrame.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
public override void UpdateHUD(Character character)
|
||||
{
|
||||
GuiFrame.Update(1.0f / 60.0f);
|
||||
fissionRateScrollBar.BarScroll = FissionRate / 100.0f;
|
||||
turbineOutputScrollBar.BarScroll = TurbineOutput / 100.0f;
|
||||
}
|
||||
}
|
||||
|
||||
private bool ToggleAutoTemp(GUITickBox tickBox)
|
||||
{
|
||||
unsentChanges = true;
|
||||
autoTemp = tickBox.Selected;
|
||||
LastUser = Character.Controlled;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void DrawMeter(SpriteBatch spriteBatch, Rectangle rect, Sprite meterSprite, float value, Vector2 range, Vector2 optimalRange, Vector2 allowedRange)
|
||||
{
|
||||
float scale = Math.Min(rect.Width / meterSprite.size.X, rect.Height / meterSprite.size.Y);
|
||||
Vector2 pos = new Vector2(rect.Center.X, rect.Y + meterSprite.Origin.Y * scale);
|
||||
|
||||
Vector2 optimalRangeNormalized = new Vector2(
|
||||
(optimalRange.X - range.X) / (range.Y - range.X),
|
||||
(optimalRange.Y - range.X) / (range.Y - range.X));
|
||||
|
||||
Vector2 allowedRangeNormalized = new Vector2(
|
||||
(allowedRange.X - range.X) / (range.Y - range.X),
|
||||
(allowedRange.Y - range.X) / (range.Y - range.X));
|
||||
|
||||
Vector2 sectorRad = new Vector2(-1.57f, 1.57f);
|
||||
|
||||
Vector2 optimalSectorRad = new Vector2(
|
||||
MathHelper.Lerp(sectorRad.X, sectorRad.Y, optimalRangeNormalized.X),
|
||||
MathHelper.Lerp(sectorRad.X, sectorRad.Y, optimalRangeNormalized.Y));
|
||||
|
||||
Vector2 allowedSectorRad = new Vector2(
|
||||
MathHelper.Lerp(sectorRad.X, sectorRad.Y, allowedRangeNormalized.X),
|
||||
MathHelper.Lerp(sectorRad.X, sectorRad.Y, allowedRangeNormalized.Y));
|
||||
|
||||
if (optimalRangeNormalized.X == optimalRangeNormalized.Y)
|
||||
{
|
||||
sectorSprite.Draw(spriteBatch, pos, Color.Red, MathHelper.PiOver2, scale);
|
||||
}
|
||||
else
|
||||
{
|
||||
spriteBatch.End();
|
||||
Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle;
|
||||
spriteBatch.GraphicsDevice.ScissorRectangle = new Rectangle(0,0,GameMain.GraphicsWidth, (int)(pos.Y + (meterSprite.size.Y - meterSprite.Origin.Y) * scale));
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, rasterizerState: GameMain.ScissorTestEnable);
|
||||
|
||||
sectorSprite.Draw(spriteBatch, pos, Color.LightGreen, MathHelper.PiOver2, scale);
|
||||
|
||||
sectorSprite.Draw(spriteBatch, pos, Color.Orange, optimalSectorRad.X, scale);
|
||||
sectorSprite.Draw(spriteBatch, pos, Color.Red, allowedSectorRad.X, scale);
|
||||
|
||||
sectorSprite.Draw(spriteBatch, pos, Color.Orange, MathHelper.Pi + optimalSectorRad.Y, scale);
|
||||
sectorSprite.Draw(spriteBatch, pos, Color.Red, MathHelper.Pi + allowedSectorRad.Y, scale);
|
||||
|
||||
spriteBatch.End();
|
||||
spriteBatch.GraphicsDevice.ScissorRectangle = prevScissorRect;
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred);
|
||||
}
|
||||
|
||||
meterSprite.Draw(spriteBatch, pos, 0, scale);
|
||||
|
||||
float normalizedValue = (value - range.X) / (range.Y - range.X);
|
||||
float valueRad = MathHelper.Lerp(sectorRad.X, sectorRad.Y, normalizedValue);
|
||||
meterPointer.Draw(spriteBatch, pos, valueRad, scale);
|
||||
}
|
||||
|
||||
static void UpdateGraph<T>(IList<T> graph, T newValue)
|
||||
{
|
||||
for (int i = graph.Count - 1; i > 0; i--)
|
||||
@@ -207,8 +465,13 @@ namespace Barotrauma.Items.Components
|
||||
graph[0] = newValue;
|
||||
}
|
||||
|
||||
static void DrawGraph(IList<float> graph, SpriteBatch spriteBatch, Rectangle rect, float maxVal, float xOffset, Color color)
|
||||
private void DrawGraph(IList<float> graph, SpriteBatch spriteBatch, Rectangle rect, float maxVal, float xOffset, Color color)
|
||||
{
|
||||
Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle;
|
||||
spriteBatch.End();
|
||||
spriteBatch.GraphicsDevice.ScissorRectangle = rect;
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, rasterizerState: GameMain.ScissorTestEnable);
|
||||
|
||||
float lineWidth = (float)rect.Width / (float)(graph.Count - 2);
|
||||
float yScale = (float)rect.Height / maxVal;
|
||||
|
||||
@@ -223,8 +486,16 @@ namespace Barotrauma.Items.Components
|
||||
currX -= lineWidth;
|
||||
|
||||
Vector2 newPoint = new Vector2(currX, rect.Bottom - graph[i] * yScale);
|
||||
|
||||
GUI.DrawLine(spriteBatch, prevPoint, newPoint - new Vector2(1.0f, 0), color);
|
||||
|
||||
if (graphLine == null)
|
||||
{
|
||||
GUI.DrawLine(spriteBatch, prevPoint, newPoint - new Vector2(1.0f, 0), color);
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector2 dir = Vector2.Normalize(newPoint - prevPoint);
|
||||
GUI.DrawLine(spriteBatch, graphLine.Texture, prevPoint - dir, newPoint + dir, color, 0, 5);
|
||||
}
|
||||
|
||||
prevPoint = newPoint;
|
||||
}
|
||||
@@ -232,16 +503,38 @@ namespace Barotrauma.Items.Components
|
||||
Vector2 lastPoint = new Vector2(rect.X,
|
||||
rect.Bottom - (graph[graph.Count - 1] + (graph[graph.Count - 2] - graph[graph.Count - 1]) * xOffset) * yScale);
|
||||
|
||||
GUI.DrawLine(spriteBatch, prevPoint, lastPoint, color);
|
||||
if (graphLine == null)
|
||||
{
|
||||
GUI.DrawLine(spriteBatch, prevPoint, lastPoint, color);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.DrawLine(spriteBatch, graphLine.Texture, prevPoint, lastPoint + (lastPoint - prevPoint), color, 0, 5);
|
||||
}
|
||||
|
||||
spriteBatch.End();
|
||||
spriteBatch.GraphicsDevice.ScissorRectangle = prevScissorRect;
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred);
|
||||
}
|
||||
|
||||
protected override void RemoveComponentSpecific()
|
||||
{
|
||||
graphLine.Remove();
|
||||
fissionRateMeter.Remove();
|
||||
turbineOutputMeter.Remove();
|
||||
meterPointer.Remove();
|
||||
sectorSprite.Remove();
|
||||
tempMeterFrame.Remove();
|
||||
tempMeterBar.Remove();
|
||||
tempRangeIndicator.Remove();
|
||||
}
|
||||
|
||||
public void ClientWrite(NetBuffer msg, object[] extraData = null)
|
||||
{
|
||||
msg.Write(autoTemp);
|
||||
msg.WriteRangedSingle(shutDownTemp, 0.0f, 10000.0f, 15);
|
||||
|
||||
msg.WriteRangedSingle(coolingRate, 0.0f, 100.0f, 8);
|
||||
msg.WriteRangedSingle(fissionRate, 0.0f, 100.0f, 8);
|
||||
msg.Write(shutDown);
|
||||
msg.WriteRangedSingle(targetFissionRate, 0.0f, 100.0f, 8);
|
||||
msg.WriteRangedSingle(targetTurbineOutput, 0.0f, 100.0f, 8);
|
||||
|
||||
correctionTimer = CorrectionDelay;
|
||||
}
|
||||
@@ -250,17 +543,20 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (correctionTimer > 0.0f)
|
||||
{
|
||||
StartDelayedCorrection(type, msg.ExtractBits(16 + 1 + 15 + 8 + 8), sendingTime);
|
||||
StartDelayedCorrection(type, msg.ExtractBits(1 + 1 + 8 + 8 + 8 + 8), sendingTime);
|
||||
return;
|
||||
}
|
||||
|
||||
Temperature = msg.ReadRangedSingle(0.0f, 10000.0f, 16);
|
||||
|
||||
AutoTemp = msg.ReadBoolean();
|
||||
ShutDownTemp = msg.ReadRangedSingle(0.0f, 10000.0f, 15);
|
||||
shutDown = msg.ReadBoolean();
|
||||
Temperature = msg.ReadRangedSingle(0.0f, 100.0f, 8);
|
||||
targetFissionRate = msg.ReadRangedSingle(0.0f, 100.0f, 8);
|
||||
targetTurbineOutput = msg.ReadRangedSingle(0.0f, 100.0f, 8);
|
||||
degreeOfSuccess = msg.ReadRangedSingle(0.0f, 1.0f, 8);
|
||||
|
||||
CoolingRate = msg.ReadRangedSingle(0.0f, 100.0f, 8);
|
||||
FissionRate = msg.ReadRangedSingle(0.0f, 100.0f, 8);
|
||||
fissionRateScrollBar.BarScroll = targetFissionRate / 100.0f;
|
||||
turbineOutputScrollBar.BarScroll = targetTurbineOutput / 100.0f;
|
||||
onOffSwitch.BarScroll = shutDown ? Math.Max(onOffSwitch.BarScroll, 0.55f) : Math.Min(onOffSwitch.BarScroll, 0.45f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,176 +1,565 @@
|
||||
using Barotrauma.Networking;
|
||||
using FarseerPhysics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class Steering : Powered, IServerSerializable, IClientSerializable
|
||||
{
|
||||
private GUITickBox autopilotTickBox, maintainPosTickBox;
|
||||
private GUITickBox levelEndTickBox, levelStartTickBox;
|
||||
private GUITickBox autopilotTickBox, manualTickBox;
|
||||
private GUITickBox maintainPosTickBox, levelEndTickBox, levelStartTickBox;
|
||||
|
||||
private GUIFrame autoPilotControlsDisabler;
|
||||
|
||||
private GUIComponent steerArea;
|
||||
|
||||
private GUITextBlock pressureWarningText;
|
||||
|
||||
private GUITextBlock tipContainer;
|
||||
|
||||
private string noPowerTip, autoPilotMaintainPosTip, autoPilotLevelStartTip, autoPilotLevelEndTip;
|
||||
|
||||
private Vector2 keyboardInput = Vector2.Zero;
|
||||
private float inputCumulation;
|
||||
|
||||
private bool levelStartSelected;
|
||||
public bool LevelStartSelected
|
||||
{
|
||||
get { return levelStartTickBox.Selected; }
|
||||
set { levelStartTickBox.Selected = value; }
|
||||
}
|
||||
|
||||
private bool levelEndSelected;
|
||||
public bool LevelEndSelected
|
||||
{
|
||||
get { return levelEndTickBox.Selected; }
|
||||
set { levelEndTickBox.Selected = value; }
|
||||
}
|
||||
|
||||
private bool maintainPos;
|
||||
public bool MaintainPos
|
||||
{
|
||||
get { return maintainPosTickBox.Selected; }
|
||||
set { maintainPosTickBox.Selected = value; }
|
||||
}
|
||||
|
||||
public bool DockingModeEnabled
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public DockingPort DockingSource, DockingTarget;
|
||||
|
||||
partial void InitProjSpecific()
|
||||
{
|
||||
autopilotTickBox = new GUITickBox(new Rectangle(0, 25, 20, 20), TextManager.Get("SteeringAutoPilot"), Alignment.TopLeft, GuiFrame);
|
||||
autopilotTickBox.OnSelected = (GUITickBox box) =>
|
||||
int viewSize = (int)Math.Min(GuiFrame.Rect.Width - 150, GuiFrame.Rect.Height * 0.9f);
|
||||
var controlContainer = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.35f), GuiFrame.RectTransform, Anchor.CenterLeft)
|
||||
{ MinSize = new Point(150, 0), AbsoluteOffset = new Point((int)(viewSize * 0.99f), (int)(viewSize * 0.05f)) }, "SonarFrame");
|
||||
var paddedControlContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.8f), controlContainer.RectTransform, Anchor.Center))
|
||||
{
|
||||
AutoPilot = box.Selected;
|
||||
unsentChanges = true;
|
||||
|
||||
return true;
|
||||
RelativeSpacing = 0.03f,
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
maintainPosTickBox = new GUITickBox(new Rectangle(5, 50, 15, 15), TextManager.Get("SteeringMaintainPos"), Alignment.TopLeft, GUI.SmallFont, GuiFrame);
|
||||
maintainPosTickBox.Enabled = false;
|
||||
maintainPosTickBox.OnSelected = ToggleMaintainPosition;
|
||||
var statusContainer = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.25f), GuiFrame.RectTransform, Anchor.BottomLeft)
|
||||
{ MinSize = new Point(150, 0), AbsoluteOffset = new Point((int)(viewSize * 0.9f), 0) }, "SonarFrame");
|
||||
var paddedStatusContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), statusContainer.RectTransform, Anchor.Center))
|
||||
{
|
||||
RelativeSpacing = 0.03f,
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
levelStartTickBox = new GUITickBox(
|
||||
new Rectangle(5, 70, 15, 15),
|
||||
manualTickBox = new GUITickBox(new RectTransform(new Vector2(0.3f, 0.3f), paddedControlContainer.RectTransform),
|
||||
TextManager.Get("SteeringManual"), style: "GUIRadioButton")
|
||||
{
|
||||
Selected = true,
|
||||
OnSelected = (GUITickBox box) =>
|
||||
{
|
||||
AutoPilot = !box.Selected;
|
||||
unsentChanges = true;
|
||||
user = Character.Controlled;
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
autopilotTickBox = new GUITickBox(new RectTransform(new Vector2(0.3f, 0.3f), paddedControlContainer.RectTransform),
|
||||
TextManager.Get("SteeringAutoPilot"), style: "GUIRadioButton")
|
||||
{
|
||||
OnSelected = (GUITickBox box) =>
|
||||
{
|
||||
AutoPilot = box.Selected;
|
||||
if (AutoPilot && MaintainPos)
|
||||
{
|
||||
posToMaintain = controlledSub == null ? item.WorldPosition : controlledSub.WorldPosition;
|
||||
}
|
||||
unsentChanges = true;
|
||||
user = Character.Controlled;
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
GUITickBox.CreateRadioButtonGroup(new List<GUITickBox> { manualTickBox, autopilotTickBox });
|
||||
|
||||
var autoPilotControls = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.6f), paddedControlContainer.RectTransform), "InnerFrame");
|
||||
var paddedAutoPilotControls = new GUILayoutGroup(new RectTransform(new Vector2(0.8f), autoPilotControls.RectTransform, Anchor.Center))
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.03f
|
||||
};
|
||||
|
||||
maintainPosTickBox = new GUITickBox(new RectTransform(new Vector2(0.2f, 0.2f), paddedAutoPilotControls.RectTransform),
|
||||
TextManager.Get("SteeringMaintainPos"), font: GUI.SmallFont)
|
||||
{
|
||||
Enabled = false,
|
||||
Selected = maintainPos,
|
||||
OnSelected = tickBox =>
|
||||
{
|
||||
if (maintainPos != tickBox.Selected)
|
||||
{
|
||||
unsentChanges = true;
|
||||
user = Character.Controlled;
|
||||
maintainPos = tickBox.Selected;
|
||||
if (maintainPos)
|
||||
{
|
||||
if (controlledSub == null)
|
||||
{
|
||||
posToMaintain = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
posToMaintain = controlledSub.WorldPosition;
|
||||
}
|
||||
}
|
||||
else if (!LevelEndSelected && !LevelStartSelected)
|
||||
{
|
||||
AutoPilot = false;
|
||||
}
|
||||
if (!maintainPos)
|
||||
{
|
||||
posToMaintain = null;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
levelStartTickBox = new GUITickBox(new RectTransform(new Vector2(0.2f, 0.2f), paddedAutoPilotControls.RectTransform),
|
||||
GameMain.GameSession?.StartLocation == null ? "" : ToolBox.LimitString(GameMain.GameSession.StartLocation.Name, 20),
|
||||
Alignment.TopLeft, GUI.SmallFont, GuiFrame);
|
||||
levelStartTickBox.Enabled = false;
|
||||
levelStartTickBox.OnSelected = SelectDestination;
|
||||
font: GUI.SmallFont)
|
||||
{
|
||||
Enabled = false,
|
||||
Selected = levelStartSelected,
|
||||
OnSelected = tickBox =>
|
||||
{
|
||||
if (levelStartSelected != tickBox.Selected)
|
||||
{
|
||||
unsentChanges = true;
|
||||
user = Character.Controlled;
|
||||
levelStartSelected = tickBox.Selected;
|
||||
levelEndSelected = !levelStartSelected;
|
||||
if (levelStartSelected)
|
||||
{
|
||||
UpdatePath();
|
||||
}
|
||||
else if (!MaintainPos && !LevelEndSelected)
|
||||
{
|
||||
AutoPilot = false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
levelEndTickBox = new GUITickBox(
|
||||
new Rectangle(5, 90, 15, 15),
|
||||
levelEndTickBox = new GUITickBox(new RectTransform(new Vector2(0.2f, 0.2f), paddedAutoPilotControls.RectTransform),
|
||||
GameMain.GameSession?.EndLocation == null ? "" : ToolBox.LimitString(GameMain.GameSession.EndLocation.Name, 20),
|
||||
Alignment.TopLeft, GUI.SmallFont, GuiFrame);
|
||||
levelEndTickBox.Enabled = false;
|
||||
levelEndTickBox.OnSelected = SelectDestination;
|
||||
font: GUI.SmallFont)
|
||||
{
|
||||
Enabled = false,
|
||||
Selected = levelEndSelected,
|
||||
OnSelected = tickBox =>
|
||||
{
|
||||
if (levelEndSelected != tickBox.Selected)
|
||||
{
|
||||
unsentChanges = true;
|
||||
user = Character.Controlled;
|
||||
levelEndSelected = tickBox.Selected;
|
||||
levelStartSelected = !levelEndSelected;
|
||||
if (levelEndSelected)
|
||||
{
|
||||
UpdatePath();
|
||||
}
|
||||
else if (!MaintainPos && !LevelStartSelected)
|
||||
{
|
||||
AutoPilot = false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
autoPilotControlsDisabler = new GUIFrame(new RectTransform(Vector2.One, autoPilotControls.RectTransform), "InnerFrame");
|
||||
|
||||
GUITickBox.CreateRadioButtonGroup(new List<GUITickBox> { maintainPosTickBox, levelStartTickBox, levelEndTickBox });
|
||||
|
||||
string steeringVelX = TextManager.Get("SteeringVelocityX");
|
||||
string steeringVelY = TextManager.Get("SteeringVelocityY");
|
||||
string steeringDepth = TextManager.Get("SteeringDepth");
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), paddedStatusContainer.RectTransform), "")
|
||||
{
|
||||
TextGetter = () =>
|
||||
{
|
||||
Vector2 vel = controlledSub == null ? Vector2.Zero : controlledSub.Velocity;
|
||||
var realWorldVel = ConvertUnits.ToDisplayUnits(vel.Y * Physics.DisplayToRealWorldRatio) * 3.6f;
|
||||
return steeringVelY.Replace("[kph]", ((int)-realWorldVel).ToString());
|
||||
}
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), paddedStatusContainer.RectTransform), "")
|
||||
{
|
||||
TextGetter = () =>
|
||||
{
|
||||
Vector2 vel = controlledSub == null ? Vector2.Zero : controlledSub.Velocity;
|
||||
var realWorldVel = ConvertUnits.ToDisplayUnits(vel.X * Physics.DisplayToRealWorldRatio) * 3.6f;
|
||||
return steeringVelX.Replace("[kph]", ((int)realWorldVel).ToString());
|
||||
}
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), paddedStatusContainer.RectTransform), "")
|
||||
{
|
||||
TextGetter = () =>
|
||||
{
|
||||
Vector2 pos = controlledSub == null ? Vector2.Zero : controlledSub.Position;
|
||||
float realWorldDepth = Level.Loaded == null ? 0.0f : Math.Abs(pos.Y - Level.Loaded.Size.Y) * Physics.DisplayToRealWorldRatio;
|
||||
return steeringDepth.Replace("[m]", ((int)realWorldDepth).ToString());
|
||||
}
|
||||
};
|
||||
|
||||
pressureWarningText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), paddedStatusContainer.RectTransform), TextManager.Get("SteeringDepthWarning"), Color.Red)
|
||||
{
|
||||
Visible = false
|
||||
};
|
||||
|
||||
tipContainer = new GUITextBlock(new RectTransform(new Vector2(0.25f, 0.12f), GuiFrame.RectTransform, Anchor.BottomLeft)
|
||||
{ MinSize = new Point(150, 0), RelativeOffset = new Vector2(0.0f, -0.05f) }, "", wrap: true, style: "GUIToolTip")
|
||||
{
|
||||
AutoScale = true
|
||||
};
|
||||
|
||||
noPowerTip = TextManager.Get("SteeringNoPowerTip");
|
||||
autoPilotMaintainPosTip = TextManager.Get("SteeringAutoPilotMaintainPosTip");
|
||||
autoPilotLevelStartTip = TextManager.Get("SteeringAutoPilotLocationTip").Replace("[locationname]",
|
||||
GameMain.GameSession?.StartLocation == null ? "Start" : GameMain.GameSession.StartLocation.Name);
|
||||
autoPilotLevelEndTip = TextManager.Get("SteeringAutoPilotLocationTip").Replace("[locationname]",
|
||||
GameMain.GameSession?.EndLocation == null ? "End" : GameMain.GameSession.EndLocation.Name);
|
||||
|
||||
steerArea = new GUICustomComponent(new RectTransform(new Point(viewSize), GuiFrame.RectTransform, Anchor.CenterLeft),
|
||||
(spriteBatch, guiCustomComponent) => { DrawHUD(spriteBatch, guiCustomComponent.Rect); }, null);
|
||||
}
|
||||
|
||||
private bool ToggleMaintainPosition(GUITickBox tickBox)
|
||||
/// <summary>
|
||||
/// Makes the sonar view CustomComponent render the steering HUD, preventing it from being drawn behing the sonar
|
||||
/// </summary>
|
||||
public void AttachToSonarHUD(GUICustomComponent sonarView)
|
||||
{
|
||||
unsentChanges = true;
|
||||
|
||||
levelStartTickBox.Selected = false;
|
||||
levelEndTickBox.Selected = false;
|
||||
|
||||
if (item.Submarine == null)
|
||||
{
|
||||
posToMaintain = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
posToMaintain = item.Submarine.WorldPosition;
|
||||
}
|
||||
|
||||
tickBox.Selected = true;
|
||||
|
||||
return true;
|
||||
steerArea.Visible = false;
|
||||
sonarView.OnDraw += (spriteBatch, guiCustomComponent) => { DrawHUD(spriteBatch, guiCustomComponent.Rect); };
|
||||
}
|
||||
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
public void DrawHUD(SpriteBatch spriteBatch, Rectangle rect)
|
||||
{
|
||||
//if (voltage < minVoltage) return;
|
||||
|
||||
int width = GuiFrame.Rect.Width, height = GuiFrame.Rect.Height;
|
||||
int x = GuiFrame.Rect.X;
|
||||
int y = GuiFrame.Rect.Y;
|
||||
|
||||
GuiFrame.Draw(spriteBatch);
|
||||
|
||||
int width = rect.Width, height = rect.Height;
|
||||
int x = rect.X;
|
||||
int y = rect.Y;
|
||||
|
||||
if (voltage < minVoltage && currPowerConsumption > 0.0f) return;
|
||||
|
||||
Rectangle velRect = new Rectangle(x + 20, y + 20, width - 40, height - 40);
|
||||
//GUI.DrawRectangle(spriteBatch, velRect, Color.White, false);
|
||||
|
||||
if (item.Submarine != null && Level.Loaded != null)
|
||||
{
|
||||
Vector2 realWorldVelocity = ConvertUnits.ToDisplayUnits(item.Submarine.Velocity * Physics.DisplayToRealWorldRatio) * 3.6f;
|
||||
float realWorldDepth = Math.Abs(item.Submarine.Position.Y - Level.Loaded.Size.Y) * Physics.DisplayToRealWorldRatio;
|
||||
GUI.DrawString(spriteBatch, new Vector2(x + 20, y + height - 65),
|
||||
TextManager.Get("SteeringVelocityX").Replace("[kph]", ((int)realWorldVelocity.X).ToString()), Color.LightGreen, null, 0, GUI.SmallFont);
|
||||
GUI.DrawString(spriteBatch, new Vector2(x + 20, y + height - 50),
|
||||
TextManager.Get("SteeringVelocityY").Replace("[kph]", ((int)-realWorldVelocity.Y).ToString()), Color.LightGreen, null, 0, GUI.SmallFont);
|
||||
|
||||
GUI.DrawString(spriteBatch, new Vector2(x + 20, y + height - 30),
|
||||
TextManager.Get("SteeringDepth").Replace("[m]", ((int)realWorldDepth).ToString()), Color.LightGreen, null, 0, GUI.SmallFont);
|
||||
}
|
||||
|
||||
Rectangle velRect = new Rectangle(x + 20, y + 20, width - 40, height - 40);
|
||||
GUI.DrawLine(spriteBatch,
|
||||
new Vector2(velRect.Center.X, velRect.Center.Y),
|
||||
new Vector2(velRect.Center.X + currVelocity.X, velRect.Center.Y - currVelocity.Y),
|
||||
Color.Gray);
|
||||
|
||||
Vector2 targetVelPos = new Vector2(velRect.Center.X + targetVelocity.X, velRect.Center.Y - targetVelocity.Y);
|
||||
if (!AutoPilot)
|
||||
{
|
||||
Vector2 unitSteeringInput = steeringInput / 100.0f;
|
||||
//map input from rectangle to circle
|
||||
Vector2 steeringInputPos = new Vector2(
|
||||
steeringInput.X * (float)Math.Sqrt(1.0f - 0.5f * unitSteeringInput.Y * unitSteeringInput.Y),
|
||||
-steeringInput.Y * (float)Math.Sqrt(1.0f - 0.5f * unitSteeringInput.X * unitSteeringInput.X));
|
||||
steeringInputPos.X += velRect.Center.X;
|
||||
steeringInputPos.Y += velRect.Center.Y;
|
||||
|
||||
GUI.DrawLine(spriteBatch,
|
||||
new Vector2(velRect.Center.X, velRect.Center.Y),
|
||||
steeringInputPos,
|
||||
Color.LightGray);
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)steeringInputPos.X - 5, (int)steeringInputPos.Y - 5, 10, 10), Color.White);
|
||||
|
||||
//if (keyboardInput.Length() > 0 || Vector2.Distance(PlayerInput.MousePosition, new Vector2(velRect.Center.X, velRect.Center.Y)) < 200.0f)
|
||||
if (velRect.Contains(PlayerInput.MousePosition))
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)steeringInputPos.X - 10, (int)steeringInputPos.Y - 10, 20, 20), Color.Red);
|
||||
}
|
||||
}
|
||||
else if (posToMaintain.HasValue && !LevelStartSelected && !LevelEndSelected)
|
||||
{
|
||||
Sonar sonar = item.GetComponent<Sonar>();
|
||||
if (sonar != null && controlledSub != null)
|
||||
{
|
||||
Vector2 displayPosToMaintain = ((posToMaintain.Value - sonar.DisplayOffset * sonar.Zoom - controlledSub.WorldPosition)) / sonar.Range * sonar.DisplayRadius * sonar.Zoom;
|
||||
displayPosToMaintain.Y = -displayPosToMaintain.Y;
|
||||
displayPosToMaintain = displayPosToMaintain.ClampLength(velRect.Width / 2);
|
||||
displayPosToMaintain = velRect.Center.ToVector2() + displayPosToMaintain;
|
||||
|
||||
float crossHairSize = 8.0f;
|
||||
Color crosshairColor = Color.Orange * (0.5f + ((float)Math.Sin(Timing.TotalTime * 5.0f) + 1.0f) / 4.0f);
|
||||
|
||||
GUI.DrawLine(spriteBatch, displayPosToMaintain + Vector2.UnitY * crossHairSize, displayPosToMaintain - Vector2.UnitY * crossHairSize, crosshairColor, width: 3);
|
||||
GUI.DrawLine(spriteBatch, displayPosToMaintain + Vector2.UnitX * crossHairSize, displayPosToMaintain - Vector2.UnitX * crossHairSize, crosshairColor, width: 3);
|
||||
|
||||
Vector2 neutralPos = ((controlledSub.WorldPosition - sonar.DisplayOffset * sonar.Zoom - controlledSub.WorldPosition)) / sonar.Range * sonar.DisplayRadius * sonar.Zoom;
|
||||
|
||||
neutralPos.Y = -neutralPos.Y;
|
||||
neutralPos = neutralPos.ClampLength(velRect.Width / 2);
|
||||
neutralPos = velRect.Center.ToVector2() + neutralPos;
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)neutralPos.X - 5, (int)neutralPos.Y - 5, 10, 10), Color.Orange);
|
||||
}
|
||||
}
|
||||
|
||||
//map velocity from rectangle to circle
|
||||
Vector2 unitTargetVel = targetVelocity / 100.0f;
|
||||
Vector2 steeringPos = new Vector2(
|
||||
targetVelocity.X * 0.9f * (float)Math.Sqrt(1.0f - 0.5f * unitTargetVel.Y * unitTargetVel.Y),
|
||||
-targetVelocity.Y * 0.9f * (float)Math.Sqrt(1.0f - 0.5f * unitTargetVel.X * unitTargetVel.X));
|
||||
steeringPos.X += velRect.Center.X;
|
||||
steeringPos.Y += velRect.Center.Y;
|
||||
|
||||
GUI.DrawLine(spriteBatch,
|
||||
new Vector2(velRect.Center.X, velRect.Center.Y),
|
||||
targetVelPos,
|
||||
Color.LightGray);
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)targetVelPos.X - 5, (int)targetVelPos.Y - 5, 10, 10), Color.White);
|
||||
|
||||
if (Vector2.Distance(PlayerInput.MousePosition, new Vector2(velRect.Center.X, velRect.Center.Y)) < 200.0f)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)targetVelPos.X - 10, (int)targetVelPos.Y - 10, 20, 20), Color.Red);
|
||||
}
|
||||
steeringPos,
|
||||
Color.CadetBlue, 0, 2);
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
public void DebugDrawHUD(SpriteBatch spriteBatch, Vector2 transducerCenter, float displayScale, float displayRadius, Vector2 center)
|
||||
{
|
||||
GuiFrame.AddToGUIUpdateList();
|
||||
}
|
||||
if (SteeringPath == null) return;
|
||||
|
||||
public override void UpdateHUD(Character character)
|
||||
{
|
||||
GuiFrame.Update(1.0f / 60.0f);
|
||||
|
||||
if (voltage < minVoltage && currPowerConsumption > 0.0f) return;
|
||||
|
||||
if (Vector2.Distance(PlayerInput.MousePosition, new Vector2(GuiFrame.Rect.Center.X, GuiFrame.Rect.Center.Y)) < 200.0f)
|
||||
Vector2 prevPos = Vector2.Zero;
|
||||
foreach (WayPoint wp in SteeringPath.Nodes)
|
||||
{
|
||||
if (PlayerInput.LeftButtonHeld())
|
||||
Vector2 pos = (wp.Position - transducerCenter) * displayScale;
|
||||
if (pos.Length() > displayRadius) continue;
|
||||
|
||||
pos.Y = -pos.Y;
|
||||
pos += center;
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X - 3 / 2, (int)pos.Y - 3, 6, 6), (SteeringPath.CurrentNode == wp) ? Color.LightGreen : Color.Green, false);
|
||||
|
||||
if (prevPos != Vector2.Zero)
|
||||
{
|
||||
TargetVelocity = PlayerInput.MousePosition - new Vector2(GuiFrame.Rect.Center.X, GuiFrame.Rect.Center.Y);
|
||||
targetVelocity.Y = -targetVelocity.Y;
|
||||
GUI.DrawLine(spriteBatch, pos, prevPos, Color.Green);
|
||||
}
|
||||
|
||||
unsentChanges = true;
|
||||
prevPos = pos;
|
||||
}
|
||||
|
||||
foreach (ObstacleDebugInfo obstacle in debugDrawObstacles)
|
||||
{
|
||||
Vector2 pos1 = (obstacle.Point1 - transducerCenter) * displayScale;
|
||||
pos1.Y = -pos1.Y;
|
||||
pos1 += center;
|
||||
Vector2 pos2 = (obstacle.Point2 - transducerCenter) * displayScale;
|
||||
pos2.Y = -pos2.Y;
|
||||
pos2 += center;
|
||||
|
||||
GUI.DrawLine(spriteBatch,
|
||||
pos1,
|
||||
pos2,
|
||||
Color.Red * 0.6f, width: 3);
|
||||
|
||||
if (obstacle.Intersection.HasValue)
|
||||
{
|
||||
Vector2 intersectionPos = (obstacle.Intersection.Value - transducerCenter) *displayScale;
|
||||
intersectionPos.Y = -intersectionPos.Y;
|
||||
intersectionPos += center;
|
||||
GUI.DrawRectangle(spriteBatch, intersectionPos - Vector2.One * 2, Vector2.One * 4, Color.Red);
|
||||
}
|
||||
|
||||
Vector2 obstacleCenter = (pos1 + pos2) / 2;
|
||||
if (obstacle.AvoidStrength.LengthSquared() > 0.01f)
|
||||
{
|
||||
GUI.DrawLine(spriteBatch,
|
||||
obstacleCenter,
|
||||
obstacleCenter + new Vector2(obstacle.AvoidStrength.X, -obstacle.AvoidStrength.Y) * 100,
|
||||
Color.Lerp(Color.Green, Color.Orange, obstacle.Dot), width: 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool SelectDestination(GUITickBox tickBox)
|
||||
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
||||
{
|
||||
unsentChanges = true;
|
||||
|
||||
if (tickBox == levelStartTickBox)
|
||||
if (steerArea.Rect.Contains(PlayerInput.MousePosition))
|
||||
{
|
||||
levelEndTickBox.Selected = false;
|
||||
if (!PlayerInput.KeyDown(InputType.Select) && !PlayerInput.KeyHit(InputType.Select))
|
||||
{
|
||||
Character.DisableControls = true;
|
||||
}
|
||||
}
|
||||
|
||||
autoPilotControlsDisabler.Visible = !AutoPilot;
|
||||
|
||||
if (voltage < minVoltage && currPowerConsumption > 0.0f)
|
||||
{
|
||||
tipContainer.Visible = true;
|
||||
tipContainer.Text = noPowerTip;
|
||||
return;
|
||||
}
|
||||
|
||||
tipContainer.Visible = AutoPilot;
|
||||
if (AutoPilot)
|
||||
{
|
||||
if (maintainPos)
|
||||
{
|
||||
tipContainer.Text = autoPilotMaintainPosTip;
|
||||
}
|
||||
else if (LevelStartSelected)
|
||||
{
|
||||
tipContainer.Text = autoPilotLevelStartTip;
|
||||
}
|
||||
else if (LevelEndSelected)
|
||||
{
|
||||
tipContainer.Text = autoPilotLevelEndTip;
|
||||
}
|
||||
|
||||
if (DockingModeEnabled && DockingTarget != null)
|
||||
{
|
||||
posToMaintain += ConvertUnits.ToDisplayUnits(DockingTarget.Item.Submarine.Velocity) * deltaTime;
|
||||
}
|
||||
}
|
||||
|
||||
pressureWarningText.Visible = item.Submarine != null && item.Submarine.AtDamageDepth && Timing.TotalTime % 1.0f < 0.5f;
|
||||
|
||||
if (Vector2.Distance(PlayerInput.MousePosition, steerArea.Rect.Center.ToVector2()) < steerArea.Rect.Width / 2)
|
||||
{
|
||||
if (PlayerInput.LeftButtonHeld())
|
||||
{
|
||||
Vector2 inputPos = PlayerInput.MousePosition - steerArea.Rect.Center.ToVector2();
|
||||
inputPos.Y = -inputPos.Y;
|
||||
if (AutoPilot && !LevelStartSelected && !LevelEndSelected)
|
||||
{
|
||||
posToMaintain = controlledSub == null ?
|
||||
item.WorldPosition :
|
||||
controlledSub.WorldPosition + (sonar.DisplayOffset * sonar.Zoom) + inputPos / sonar.DisplayRadius * sonar.Range / sonar.Zoom;
|
||||
}
|
||||
else
|
||||
{
|
||||
SteeringInput = inputPos;
|
||||
}
|
||||
unsentChanges = true;
|
||||
user = Character.Controlled;
|
||||
}
|
||||
}
|
||||
if (!AutoPilot && Character.DisableControls)
|
||||
{
|
||||
steeringAdjustSpeed = character == null ? 0.2f : MathHelper.Lerp(0.2f, 1.0f, character.GetSkillLevel("helm") / 100.0f);
|
||||
Vector2 input = Vector2.Zero;
|
||||
if (PlayerInput.KeyDown(InputType.Left))
|
||||
{
|
||||
input -= Vector2.UnitX;
|
||||
}
|
||||
if (PlayerInput.KeyDown(InputType.Right))
|
||||
{
|
||||
input += Vector2.UnitX;
|
||||
}
|
||||
if (PlayerInput.KeyDown(InputType.Up))
|
||||
{
|
||||
input += Vector2.UnitY;
|
||||
}
|
||||
if (PlayerInput.KeyDown(InputType.Down))
|
||||
{
|
||||
input -= Vector2.UnitY;
|
||||
}
|
||||
if (PlayerInput.KeyDown(Keys.LeftShift))
|
||||
{
|
||||
SteeringInput += input * deltaTime * 200;
|
||||
inputCumulation = 0;
|
||||
keyboardInput = Vector2.Zero;
|
||||
unsentChanges = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
float step = deltaTime * 5;
|
||||
if (input.Length() > 0)
|
||||
{
|
||||
inputCumulation += step;
|
||||
}
|
||||
else
|
||||
{
|
||||
inputCumulation -= step;
|
||||
}
|
||||
float maxCumulation = 1;
|
||||
inputCumulation = MathHelper.Clamp(inputCumulation, 0, maxCumulation);
|
||||
float length = MathHelper.Lerp(0, 0.2f, MathUtils.InverseLerp(0, maxCumulation, inputCumulation));
|
||||
var normalizedInput = Vector2.Normalize(input);
|
||||
if (MathUtils.IsValid(normalizedInput))
|
||||
{
|
||||
keyboardInput += normalizedInput * length;
|
||||
}
|
||||
if (keyboardInput.LengthSquared() > 0.01f)
|
||||
{
|
||||
SteeringInput += keyboardInput;
|
||||
unsentChanges = true;
|
||||
user = Character.Controlled;
|
||||
keyboardInput *= MathHelper.Clamp(1 - step, 0, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
levelStartTickBox.Selected = false;
|
||||
inputCumulation = 0;
|
||||
keyboardInput = Vector2.Zero;
|
||||
}
|
||||
|
||||
maintainPosTickBox.Selected = false;
|
||||
posToMaintain = null;
|
||||
tickBox.Selected = true;
|
||||
|
||||
UpdatePath();
|
||||
float closestDist = DockingAssistThreshold * DockingAssistThreshold;
|
||||
DockingModeEnabled = false;
|
||||
DockingSource = null;
|
||||
DockingTarget = null;
|
||||
foreach (DockingPort sourcePort in DockingPort.List)
|
||||
{
|
||||
if (sourcePort.Docked || sourcePort.Item.Submarine == null) { continue; }
|
||||
if (sourcePort.Item.Submarine != controlledSub) { continue; }
|
||||
|
||||
return true;
|
||||
int sourceDir = sourcePort.IsHorizontal ?
|
||||
Math.Sign(sourcePort.Item.WorldPosition.X - sourcePort.Item.Submarine.WorldPosition.X) :
|
||||
Math.Sign(sourcePort.Item.WorldPosition.Y - sourcePort.Item.Submarine.WorldPosition.Y);
|
||||
|
||||
foreach (DockingPort targetPort in DockingPort.List)
|
||||
{
|
||||
if (targetPort.Docked || targetPort.Item.Submarine == null) { continue; }
|
||||
if (targetPort.Item.Submarine == controlledSub || targetPort.IsHorizontal != sourcePort.IsHorizontal) { continue; }
|
||||
if (Level.Loaded != null && targetPort.Item.Submarine.WorldPosition.Y > Level.Loaded.Size.Y) { continue; }
|
||||
|
||||
int targetDir = targetPort.IsHorizontal ?
|
||||
Math.Sign(targetPort.Item.WorldPosition.X - targetPort.Item.Submarine.WorldPosition.X) :
|
||||
Math.Sign(targetPort.Item.WorldPosition.Y - targetPort.Item.Submarine.WorldPosition.Y);
|
||||
|
||||
if (sourceDir == targetDir) { continue; }
|
||||
|
||||
float dist = Vector2.DistanceSquared(sourcePort.Item.WorldPosition, targetPort.Item.WorldPosition);
|
||||
if (dist < closestDist)
|
||||
{
|
||||
DockingModeEnabled = true;
|
||||
DockingSource = sourcePort;
|
||||
DockingTarget = targetPort;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientWrite(Lidgren.Network.NetBuffer msg, object[] extraData = null)
|
||||
@@ -180,8 +569,8 @@ namespace Barotrauma.Items.Components
|
||||
if (!autoPilot)
|
||||
{
|
||||
//no need to write steering info if autopilot is controlling
|
||||
msg.Write(targetVelocity.X);
|
||||
msg.Write(targetVelocity.Y);
|
||||
msg.Write(steeringInput.X);
|
||||
msg.Write(steeringInput.Y);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -202,11 +591,13 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
long msgStartPos = msg.Position;
|
||||
|
||||
bool autoPilot = msg.ReadBoolean();
|
||||
Vector2 newTargetVelocity = targetVelocity;
|
||||
bool maintainPos = false;
|
||||
Vector2? newPosToMaintain = null;
|
||||
bool headingToStart = false;
|
||||
bool autoPilot = msg.ReadBoolean();
|
||||
Vector2 newSteeringInput = steeringInput;
|
||||
Vector2 newTargetVelocity = targetVelocity;
|
||||
float newSteeringAdjustSpeed = steeringAdjustSpeed;
|
||||
bool maintainPos = false;
|
||||
Vector2? newPosToMaintain = null;
|
||||
bool headingToStart = false;
|
||||
|
||||
if (autoPilot)
|
||||
{
|
||||
@@ -224,7 +615,9 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else
|
||||
{
|
||||
newSteeringInput = new Vector2(msg.ReadFloat(), msg.ReadFloat());
|
||||
newTargetVelocity = new Vector2(msg.ReadFloat(), msg.ReadFloat());
|
||||
newSteeringAdjustSpeed = msg.ReadFloat();
|
||||
}
|
||||
|
||||
if (correctionTimer > 0.0f)
|
||||
@@ -239,11 +632,12 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (!AutoPilot)
|
||||
{
|
||||
targetVelocity = newTargetVelocity;
|
||||
SteeringInput = newSteeringInput;
|
||||
TargetVelocity = newTargetVelocity;
|
||||
steeringAdjustSpeed = newSteeringAdjustSpeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
MaintainPos = newPosToMaintain != null;
|
||||
posToMaintain = newPosToMaintain;
|
||||
|
||||
|
||||
@@ -2,20 +2,48 @@
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class PowerContainer : Powered, IDrawableComponent, IServerSerializable, IClientSerializable
|
||||
{
|
||||
private GUIProgressBar chargeIndicator;
|
||||
private GUIScrollBar rechargeSpeedSlider;
|
||||
|
||||
partial void InitProjSpecific()
|
||||
{
|
||||
if (canBeSelected)
|
||||
if (GuiFrame == null) return;
|
||||
|
||||
GUILayoutGroup paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.7f), GuiFrame.RectTransform, Anchor.Center))
|
||||
{ RelativeSpacing = 0.1f, Stretch = true };
|
||||
|
||||
string rechargeStr = TextManager.Get("PowerContainerRechargeRate");
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), paddedFrame.RectTransform), "RechargeRate", textAlignment: Alignment.Center)
|
||||
{
|
||||
var button = new GUIButton(new Rectangle(160, 50, 30, 30), "-", "", GuiFrame);
|
||||
button.OnClicked = (GUIButton btn, object obj) =>
|
||||
TextGetter = () =>
|
||||
{
|
||||
RechargeSpeed = rechargeSpeed - maxRechargeSpeed * 0.1f;
|
||||
return rechargeStr.Replace("[rate]", ((int)((rechargeSpeed / maxRechargeSpeed) * 100.0f)).ToString());
|
||||
}
|
||||
};
|
||||
|
||||
var sliderArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.2f), paddedFrame.RectTransform, Anchor.BottomCenter), isHorizontal: true)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.05f
|
||||
};
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), sliderArea.RectTransform),
|
||||
"0 %", textAlignment: Alignment.Center);
|
||||
rechargeSpeedSlider = new GUIScrollBar(new RectTransform(new Vector2(0.8f, 1.0f), sliderArea.RectTransform), barSize: 0.25f, style: "GUISlider")
|
||||
{
|
||||
Step = 0.1f,
|
||||
OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
|
||||
{
|
||||
float newRechargeSpeed = maxRechargeSpeed * barScroll;
|
||||
if (Math.Abs(newRechargeSpeed - rechargeSpeed) < 0.1f) return false;
|
||||
|
||||
RechargeSpeed = newRechargeSpeed;
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
@@ -26,68 +54,79 @@ namespace Barotrauma.Items.Components
|
||||
item.CreateClientEvent(this);
|
||||
correctionTimer = CorrectionDelay;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), sliderArea.RectTransform),
|
||||
"100 %", textAlignment: Alignment.Center);
|
||||
|
||||
button = new GUIButton(new Rectangle(200, 50, 30, 30), "+", "", GuiFrame);
|
||||
button.OnClicked = (GUIButton btn, object obj) =>
|
||||
string chargeStr = TextManager.Get("PowerContainerCharge");
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), paddedFrame.RectTransform), "Charge", textAlignment: Alignment.Center)
|
||||
{
|
||||
TextGetter = () =>
|
||||
{
|
||||
RechargeSpeed = rechargeSpeed + maxRechargeSpeed * 0.1f;
|
||||
return chargeStr.Replace("[charge]", (int)charge + "/" + (int)capacity).Replace("[percentage]", ((int)((charge / capacity) * 100.0f)).ToString());
|
||||
}
|
||||
};
|
||||
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
GameServer.Log(Character.Controlled.LogName + " set the recharge speed of " + item.Name + " to " + (int)((rechargeSpeed / maxRechargeSpeed) * 100.0f) + " %", ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
else if (GameMain.Client != null)
|
||||
{
|
||||
item.CreateClientEvent(this);
|
||||
correctionTimer = CorrectionDelay;
|
||||
}
|
||||
chargeIndicator = new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.2f), paddedFrame.RectTransform), barSize: 0.0f)
|
||||
{
|
||||
ProgressGetter = () =>
|
||||
{
|
||||
return charge / capacity;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
public override void OnItemLoaded()
|
||||
{
|
||||
if (rechargeSpeedSlider != null)
|
||||
{
|
||||
rechargeSpeedSlider.BarScroll = rechargeSpeed / MaxRechargeSpeed;
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
||||
{
|
||||
float chargeRatio = charge / capacity;
|
||||
chargeIndicator.Color = ToolBox.GradientLerp(chargeRatio, Color.Red, Color.Orange, Color.Green);
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing = false)
|
||||
{
|
||||
if (indicatorSize.X <= 1.0f || indicatorSize.Y <= 1.0f) return;
|
||||
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
new Vector2(item.DrawPosition.X - 4, -item.DrawPosition.Y),
|
||||
new Vector2(8, 22), Color.Black);
|
||||
new Vector2(
|
||||
item.DrawPosition.X - item.Sprite.SourceRect.Width / 2 * item.Scale + indicatorPosition.X * item.Scale,
|
||||
-item.DrawPosition.Y - item.Sprite.SourceRect.Height / 2 * item.Scale + indicatorPosition.Y * item.Scale),
|
||||
indicatorSize * item.Scale, Color.Black, depth: item.SpriteDepth - 0.00001f);
|
||||
|
||||
if (charge > 0)
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
new Vector2(item.DrawPosition.X - 3, -item.DrawPosition.Y + 1 + (20.0f * (1.0f - charge / capacity))),
|
||||
new Vector2(6, 20 * (charge / capacity)), Color.Green, true);
|
||||
{
|
||||
Color indicatorColor = ToolBox.GradientLerp(charge / capacity, Color.Red, Color.Orange, Color.Green);
|
||||
if (!isHorizontal)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
new Vector2(
|
||||
item.DrawPosition.X - item.Sprite.SourceRect.Width / 2 * item.Scale + indicatorPosition.X * item.Scale + 1,
|
||||
-item.DrawPosition.Y - item.Sprite.SourceRect.Height / 2 * item.Scale + indicatorPosition.Y * item.Scale + 1 + ((indicatorSize.Y * item.Scale) * (1.0f - charge / capacity))),
|
||||
new Vector2(indicatorSize.X * item.Scale - 2, (indicatorSize.Y * item.Scale - 2) * (charge / capacity)), indicatorColor, true,
|
||||
depth: item.SpriteDepth - 0.00001f);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
new Vector2(
|
||||
item.DrawPosition.X - item.Sprite.SourceRect.Width / 2 * item.Scale + indicatorPosition.X * item.Scale + 1 ,
|
||||
-item.DrawPosition.Y - item.Sprite.SourceRect.Height / 2 * item.Scale + indicatorPosition.Y * item.Scale + 1),
|
||||
new Vector2((indicatorSize.X * item.Scale - 2) * (charge / capacity), indicatorSize.Y * item.Scale - 2), indicatorColor, true,
|
||||
depth: item.SpriteDepth - 0.00001f);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
{
|
||||
GuiFrame.Draw(spriteBatch);
|
||||
|
||||
int x = GuiFrame.Rect.X;
|
||||
int y = GuiFrame.Rect.Y;
|
||||
//GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black, true);
|
||||
|
||||
GUI.Font.DrawString(spriteBatch,
|
||||
TextManager.Get("PowerContainerCharge").Replace("[charge]", (int)charge + "/" + (int)capacity).Replace("[percentage]", ((int)((charge / capacity) * 100.0f)).ToString()),
|
||||
new Vector2(x + 30, y + 30), Color.White);
|
||||
|
||||
GUI.Font.DrawString(spriteBatch, TextManager.Get("PowerContainerRechargeRate") + ": " + (int)((rechargeSpeed / maxRechargeSpeed) * 100.0f) + " %", new Vector2(x + 30, y + 95), Color.White);
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
{
|
||||
GuiFrame.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
public override void UpdateHUD(Character character)
|
||||
{
|
||||
GuiFrame.Update(1.0f / 60.0f);
|
||||
}
|
||||
|
||||
|
||||
public void ClientWrite(NetBuffer msg, object[] extraData)
|
||||
{
|
||||
msg.WriteRangedInteger(0, 10, (int)(rechargeSpeed / MaxRechargeSpeed * 10));
|
||||
|
||||
@@ -1,36 +1,73 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class PowerTransfer : Powered
|
||||
{
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
private GUITickBox powerIndicator;
|
||||
private GUITickBox highVoltageIndicator;
|
||||
private GUITickBox lowVoltageIndicator;
|
||||
|
||||
partial void InitProjectSpecific(XElement element)
|
||||
{
|
||||
if (!canBeSelected) return;
|
||||
if (GuiFrame == null) return;
|
||||
|
||||
int x = GuiFrame.Rect.X;
|
||||
int y = GuiFrame.Rect.Y;
|
||||
var paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.7f), GuiFrame.RectTransform, Anchor.Center), style: null);
|
||||
powerIndicator = new GUITickBox(new RectTransform(new Point(30, 30), paddedFrame.RectTransform),
|
||||
TextManager.Get("PowerTransferPowered"), style: "IndicatorLightGreen")
|
||||
{
|
||||
Enabled = false
|
||||
};
|
||||
highVoltageIndicator = new GUITickBox(new RectTransform(new Point(30, 30), paddedFrame.RectTransform) { AbsoluteOffset = new Point(0, 40) },
|
||||
TextManager.Get("PowerTransferHighVoltage"), style: "IndicatorLightRed")
|
||||
{
|
||||
ToolTip = TextManager.Get("PowerTransferTipOvervoltage"),
|
||||
Enabled = false
|
||||
};
|
||||
lowVoltageIndicator = new GUITickBox(new RectTransform(new Point(30, 30), paddedFrame.RectTransform) { AbsoluteOffset = new Point(0, 80) },
|
||||
TextManager.Get("PowerTransferLowVoltage"), style: "IndicatorLightRed")
|
||||
{
|
||||
ToolTip = TextManager.Get("PowerTransferTipLowvoltage"),
|
||||
Enabled = false
|
||||
};
|
||||
|
||||
GuiFrame.Draw(spriteBatch);
|
||||
var textContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), paddedFrame.RectTransform, Anchor.TopRight));
|
||||
|
||||
GUI.Font.DrawString(spriteBatch,
|
||||
TextManager.Get("PowerTransferPower").Replace("[power]", ((int)(-currPowerConsumption)).ToString()),
|
||||
new Vector2(x + 30, y + 30), Color.White);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), textContainer.RectTransform),
|
||||
TextManager.Get("PowerTransferPowerLabel"), font: GUI.LargeFont)
|
||||
{
|
||||
ToolTip = TextManager.Get("PowerTransferTipPower")
|
||||
};
|
||||
string powerStr = TextManager.Get("PowerTransferPower");
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), textContainer.RectTransform), "", textColor: Color.LightGreen)
|
||||
{
|
||||
ToolTip = TextManager.Get("PowerTransferTipPower"),
|
||||
TextGetter = () => { return powerStr.Replace("[power]", ((int)(-currPowerConsumption)).ToString()); }
|
||||
};
|
||||
|
||||
GUI.Font.DrawString(spriteBatch,
|
||||
TextManager.Get("PowerTransferLoad").Replace("[load]", ((int)powerLoad).ToString()),
|
||||
new Vector2(x + 30, y + 100), Color.White);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), textContainer.RectTransform),
|
||||
TextManager.Get("PowerTransferLoadLabel"), font: GUI.LargeFont)
|
||||
{
|
||||
ToolTip = TextManager.Get("PowerTransferTipLoad")
|
||||
};
|
||||
string loadStr = TextManager.Get("PowerTransferLoad");
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), textContainer.RectTransform), "", textColor: Color.LightBlue)
|
||||
{
|
||||
ToolTip = TextManager.Get("PowerTransferTipLoad"),
|
||||
TextGetter = () => { return loadStr.Replace("[load]", ((int)(powerLoad)).ToString()); }
|
||||
};
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
||||
{
|
||||
GuiFrame.AddToGUIUpdateList();
|
||||
}
|
||||
if (GuiFrame == null) return;
|
||||
|
||||
public override void UpdateHUD(Character character)
|
||||
{
|
||||
GuiFrame.Update(1.0f / 60.0f);
|
||||
float voltage = powerLoad <= 0.0f ? 1.0f : -currPowerConsumption / powerLoad;
|
||||
powerIndicator.Selected = IsActive && currPowerConsumption < -0.1f;
|
||||
highVoltageIndicator.Selected = Timing.TotalTime % 0.5f < 0.25f && powerIndicator.Selected && voltage > 1.2f;
|
||||
lowVoltageIndicator.Selected = Timing.TotalTime % 0.5f < 0.25f && powerIndicator.Selected && voltage < 0.8f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,31 @@
|
||||
namespace Barotrauma.Items.Components
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Sounds;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class Powered : ItemComponent
|
||||
{
|
||||
protected static Sound[] sparkSounds;
|
||||
protected List<RoundSound> sparkSounds;
|
||||
|
||||
private RoundSound powerOnSound;
|
||||
private bool powerOnSoundPlayed;
|
||||
|
||||
private static Sound powerOnSound;
|
||||
|
||||
partial void InitProjectSpecific(XElement element)
|
||||
{
|
||||
sparkSounds = new List<RoundSound>();
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "poweronsound":
|
||||
powerOnSound = Submarine.LoadRoundSound(subElement, false);
|
||||
break;
|
||||
case "sparksound":
|
||||
sparkSounds.Add(Submarine.LoadRoundSound(subElement, false));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
using Barotrauma.Particles;
|
||||
using FarseerPhysics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class RepairTool
|
||||
{
|
||||
public ParticleEmitter ParticleEmitter
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
private List<ParticleEmitter> ParticleEmitterHitStructure = new List<ParticleEmitter>();
|
||||
private List<ParticleEmitter> ParticleEmitterHitCharacter = new List<ParticleEmitter>();
|
||||
private List<Pair<RelatedItem, ParticleEmitter>> ParticleEmitterHitItem = new List<Pair<RelatedItem, ParticleEmitter>>();
|
||||
|
||||
partial void InitProjSpecific(XElement element)
|
||||
{
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "particleemitter":
|
||||
ParticleEmitter = new ParticleEmitter(subElement);
|
||||
break;
|
||||
case "particleemitterhititem":
|
||||
string[] identifiers = subElement.GetAttributeStringArray("identifiers", new string[0]);
|
||||
if (identifiers.Length == 0) identifiers = subElement.GetAttributeStringArray("identifier", new string[0]);
|
||||
string[] excludedIdentifiers = subElement.GetAttributeStringArray("excludedidentifiers", new string[0]);
|
||||
if (excludedIdentifiers.Length == 0) excludedIdentifiers = subElement.GetAttributeStringArray("excludedidentifier", new string[0]);
|
||||
|
||||
ParticleEmitterHitItem.Add(
|
||||
new Pair<RelatedItem, ParticleEmitter>(
|
||||
new RelatedItem(identifiers, excludedIdentifiers),
|
||||
new ParticleEmitter(subElement)));
|
||||
break;
|
||||
case "particleemitterhitstructure":
|
||||
ParticleEmitterHitStructure.Add(new ParticleEmitter(subElement));
|
||||
break;
|
||||
case "particleemitterhitcharacter":
|
||||
ParticleEmitterHitCharacter.Add(new ParticleEmitter(subElement));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
partial void UseProjSpecific(float deltaTime)
|
||||
{
|
||||
if (ParticleEmitter != null)
|
||||
{
|
||||
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
||||
ParticleEmitter.Emit(
|
||||
deltaTime, item.WorldPosition + TransformedBarrelPos,
|
||||
item.CurrentHull, particleAngle, -particleAngle);
|
||||
}
|
||||
}
|
||||
|
||||
partial void FixStructureProjSpecific(Character user, float deltaTime, Structure targetStructure, int sectionIndex)
|
||||
{
|
||||
Vector2 progressBarPos = targetStructure.SectionPosition(sectionIndex);
|
||||
if (targetStructure.Submarine != null)
|
||||
{
|
||||
progressBarPos += targetStructure.Submarine.DrawPosition;
|
||||
}
|
||||
|
||||
var progressBar = user.UpdateHUDProgressBar(
|
||||
targetStructure,
|
||||
progressBarPos,
|
||||
1.0f - targetStructure.SectionDamage(sectionIndex) / targetStructure.Health,
|
||||
Color.Red, Color.Green);
|
||||
|
||||
if (progressBar != null) progressBar.Size = new Vector2(60.0f, 20.0f);
|
||||
|
||||
Vector2 particlePos = ConvertUnits.ToDisplayUnits(pickedPosition);
|
||||
if (targetStructure.Submarine != null) particlePos += targetStructure.Submarine.DrawPosition;
|
||||
foreach (var emitter in ParticleEmitterHitStructure)
|
||||
{
|
||||
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
||||
emitter.Emit(deltaTime, particlePos, item.CurrentHull, particleAngle + MathHelper.Pi, -particleAngle + MathHelper.Pi);
|
||||
}
|
||||
}
|
||||
|
||||
partial void FixCharacterProjSpecific(Character user, float deltaTime, Character targetCharacter)
|
||||
{
|
||||
Vector2 particlePos = ConvertUnits.ToDisplayUnits(pickedPosition);
|
||||
if (targetCharacter.Submarine != null) particlePos += targetCharacter.Submarine.DrawPosition;
|
||||
foreach (var emitter in ParticleEmitterHitCharacter)
|
||||
{
|
||||
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
||||
emitter.Emit(deltaTime, particlePos, item.CurrentHull, particleAngle + MathHelper.Pi, -particleAngle + MathHelper.Pi);
|
||||
}
|
||||
}
|
||||
|
||||
partial void FixItemProjSpecific(Character user, float deltaTime, Item targetItem, float prevCondition)
|
||||
{
|
||||
if (prevCondition != targetItem.Condition)
|
||||
{
|
||||
Vector2 progressBarPos = targetItem.DrawPosition;
|
||||
var progressBar = user.UpdateHUDProgressBar(
|
||||
targetItem,
|
||||
progressBarPos,
|
||||
targetItem.Condition / 100.0f,
|
||||
Color.Red, Color.Green);
|
||||
if (progressBar != null) { progressBar.Size = new Vector2(60.0f, 20.0f); }
|
||||
}
|
||||
|
||||
Vector2 particlePos = ConvertUnits.ToDisplayUnits(pickedPosition);
|
||||
if (targetItem.Submarine != null) particlePos += targetItem.Submarine.DrawPosition;
|
||||
foreach (var emitter in ParticleEmitterHitItem)
|
||||
{
|
||||
if (!emitter.First.MatchesItem(targetItem)) continue;
|
||||
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
||||
emitter.Second.Emit(deltaTime, particlePos, item.CurrentHull, particleAngle + MathHelper.Pi, -particleAngle + MathHelper.Pi);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
using Barotrauma.Particles;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class Repairable : ItemComponent
|
||||
{
|
||||
private GUIButton repairButton;
|
||||
private GUIProgressBar progressBar;
|
||||
|
||||
private List<ParticleEmitter> particleEmitters = new List<ParticleEmitter>();
|
||||
//the corresponding particle emitter is active when the condition is within this range
|
||||
private List<Vector2> particleEmitterConditionRanges = new List<Vector2>();
|
||||
|
||||
private string repairButtonText, repairingText;
|
||||
|
||||
[Serialize("", false)]
|
||||
public string Description
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public override bool ShouldDrawHUD(Character character)
|
||||
{
|
||||
if (!HasRequiredItems(character, false)) return false;
|
||||
return (item.Condition < ShowRepairUIThreshold || (currentFixer == character && item.Condition < item.Prefab.Health));
|
||||
}
|
||||
|
||||
partial void InitProjSpecific(XElement element)
|
||||
{
|
||||
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.85f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.05f
|
||||
};
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), paddedFrame.RectTransform),
|
||||
header, textAlignment: Alignment.TopCenter, font: GUI.LargeFont);
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform),
|
||||
Description, font: GUI.SmallFont, wrap: true);
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), paddedFrame.RectTransform),
|
||||
TextManager.Get("RequiredRepairSkills"));
|
||||
for (int i = 0; i < requiredSkills.Count; i++)
|
||||
{
|
||||
var skillText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), paddedFrame.RectTransform),
|
||||
" - " + TextManager.Get("SkillName." + requiredSkills[i].Identifier) + ": " + ((int)requiredSkills[i].Level), font: GUI.SmallFont)
|
||||
{
|
||||
UserData = requiredSkills[i]
|
||||
};
|
||||
}
|
||||
|
||||
progressBar = new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.15f), paddedFrame.RectTransform),
|
||||
color: Color.Green, barSize: 0.0f);
|
||||
|
||||
repairButtonText = TextManager.Get("RepairButton");
|
||||
repairingText = TextManager.Get("Repairing");
|
||||
repairButton = new GUIButton(new RectTransform(new Vector2(0.8f, 0.15f), paddedFrame.RectTransform, Anchor.TopCenter),
|
||||
repairButtonText)
|
||||
{
|
||||
OnClicked = (btn, obj) =>
|
||||
{
|
||||
currentFixer = Character.Controlled;
|
||||
item.CreateClientEvent(this);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "emitter":
|
||||
case "particleemitter":
|
||||
particleEmitters.Add(new ParticleEmitter(subElement));
|
||||
particleEmitterConditionRanges.Add(new Vector2(
|
||||
subElement.GetAttributeFloat("mincondition", 0.0f),
|
||||
subElement.GetAttributeFloat("maxcondition", 100.0f)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
partial void UpdateProjSpecific(float deltaTime)
|
||||
{
|
||||
for (int i = 0; i < particleEmitters.Count; i++)
|
||||
{
|
||||
if (item.Condition >= particleEmitterConditionRanges[i].X && item.Condition <= particleEmitterConditionRanges[i].Y)
|
||||
{
|
||||
particleEmitters[i].Emit(deltaTime, item.WorldPosition, item.CurrentHull);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
{
|
||||
IsActive = true;
|
||||
|
||||
progressBar.BarSize = item.Condition / item.Prefab.Health;
|
||||
progressBar.Color = ToolBox.GradientLerp(item.Condition / item.Prefab.Health, Color.Red, Color.Orange, Color.Green);
|
||||
|
||||
repairButton.Enabled = currentFixer == null;
|
||||
repairButton.Text = currentFixer == null ?
|
||||
repairButtonText :
|
||||
repairingText + new string('.', ((int)(Timing.TotalTime * 2.0f) % 3) + 1);
|
||||
|
||||
System.Diagnostics.Debug.Assert(GuiFrame.GetChild(0) is GUILayoutGroup, "Repair UI hierarchy has changed, could not find skill texts");
|
||||
foreach (GUIComponent c in GuiFrame.GetChild(0).Children)
|
||||
{
|
||||
Skill skill = c.UserData as Skill;
|
||||
if (skill == null) continue;
|
||||
|
||||
GUITextBlock textBlock = (GUITextBlock)c;
|
||||
if (character.GetSkillLevel(skill.Identifier) < skill.Level)
|
||||
{
|
||||
textBlock.TextColor = Color.Red;
|
||||
}
|
||||
else
|
||||
{
|
||||
textBlock.TextColor = Color.White;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,27 +2,27 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class Connection
|
||||
{
|
||||
private static Texture2D panelTexture;
|
||||
//private static Texture2D panelTexture;
|
||||
private static Sprite connector;
|
||||
private static Sprite wireVertical;
|
||||
private static Sprite connectionSprite;
|
||||
private static Sprite connectionSpriteHighlight;
|
||||
private static List<Sprite> screwSprites;
|
||||
|
||||
private static Wire draggingConnected;
|
||||
|
||||
public static void DrawConnections(SpriteBatch spriteBatch, ConnectionPanel panel, Character character)
|
||||
{
|
||||
|
||||
int width = 400, height = 200;
|
||||
int x = GameMain.GraphicsWidth / 2 - width / 2, y = GameMain.GraphicsHeight - height;
|
||||
|
||||
Rectangle panelRect = new Rectangle(x, y, width, height);
|
||||
|
||||
spriteBatch.Draw(panelTexture, panelRect, new Rectangle(0, 512 - height, width, height), Color.White);
|
||||
|
||||
//GUI.DrawRectangle(spriteBatch, panelRect, Color.Black, true);
|
||||
Rectangle panelRect = panel.GuiFrame.Rect;
|
||||
int x = panelRect.X, y = panelRect.Y;
|
||||
int width = panelRect.Width, height = panelRect.Height;
|
||||
|
||||
bool mouseInRect = panelRect.Contains(PlayerInput.MousePosition);
|
||||
|
||||
@@ -49,14 +49,15 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
Vector2 rightPos = new Vector2(x + width - 130, y + 50);
|
||||
Vector2 leftPos = new Vector2(x + 130, y + 50);
|
||||
Vector2 rightPos = new Vector2(x + width - 130, y + 80);
|
||||
Vector2 leftPos = new Vector2(x + 130, y + 80);
|
||||
|
||||
Vector2 rightWirePos = new Vector2(x + width - 5, y + 30);
|
||||
|
||||
Vector2 leftWirePos = new Vector2(x + 5, y + 30);
|
||||
|
||||
int wireInterval = (height - 20) / Math.Max(totalWireCount, 1);
|
||||
int connectorIntervalLeft = (height - 100) / Math.Max(panel.Connections.Count(c => c.IsOutput), 1);
|
||||
int connectorIntervalRight = (height - 100) / Math.Max(panel.Connections.Count(c => !c.IsOutput), 1);
|
||||
|
||||
foreach (Connection c in panel.Connections)
|
||||
{
|
||||
@@ -67,7 +68,7 @@ namespace Barotrauma.Items.Components
|
||||
int linkIndex = c.FindWireIndex(draggingConnected.Item);
|
||||
if (linkIndex > -1)
|
||||
{
|
||||
Inventory.draggingItem = c.Wires[linkIndex].Item;
|
||||
Inventory.draggingItem = c.wires[linkIndex].Item;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +81,7 @@ namespace Barotrauma.Items.Components
|
||||
mouseInRect, equippedWire,
|
||||
wireInterval);
|
||||
|
||||
rightPos.Y += 30;
|
||||
rightPos.Y += connectorIntervalLeft;
|
||||
rightWirePos.Y += c.Wires.Count(w => w != null) * wireInterval;
|
||||
}
|
||||
else
|
||||
@@ -91,7 +92,7 @@ namespace Barotrauma.Items.Components
|
||||
mouseInRect, equippedWire,
|
||||
wireInterval);
|
||||
|
||||
leftPos.Y += 30;
|
||||
leftPos.Y += connectorIntervalRight;
|
||||
leftWirePos.Y += c.Wires.Count(w => w != null) * wireInterval;
|
||||
//leftWireX -= wireInterval;
|
||||
}
|
||||
@@ -99,7 +100,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (draggingConnected != null)
|
||||
{
|
||||
DrawWire(spriteBatch, draggingConnected, draggingConnected.Item, PlayerInput.MousePosition, new Vector2(x + width / 2, y + height), mouseInRect, null, panel);
|
||||
DrawWire(spriteBatch, draggingConnected, draggingConnected.Item, PlayerInput.MousePosition, new Vector2(x + width / 2, y + height - 10), mouseInRect, null, panel, "");
|
||||
|
||||
if (!PlayerInput.LeftButtonHeld())
|
||||
{
|
||||
@@ -124,48 +125,45 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
DrawWire(spriteBatch, equippedWire, equippedWire.Item,
|
||||
new Vector2(x + width / 2, y + height - 100),
|
||||
new Vector2(x + width / 2, y + height), mouseInRect, null, panel);
|
||||
new Vector2(x + width / 2, y + height), mouseInRect, null, panel, "");
|
||||
|
||||
if (draggingConnected == equippedWire) Inventory.draggingItem = equippedWire.Item;
|
||||
}
|
||||
}
|
||||
|
||||
//stop dragging a wire item if cursor is outside the panel
|
||||
if (mouseInRect) Inventory.draggingItem = null;
|
||||
|
||||
|
||||
spriteBatch.Draw(panelTexture, panelRect, new Rectangle(0, 0, width, height), Color.White);
|
||||
|
||||
|
||||
//stop dragging a wire item if the cursor is within any connection panel
|
||||
//(so we don't drop the item when dropping the wire on a connection)
|
||||
if (mouseInRect || GUI.MouseOn?.UserData is ConnectionPanel) Inventory.draggingItem = null;
|
||||
}
|
||||
|
||||
private void Draw(SpriteBatch spriteBatch, ConnectionPanel panel, Vector2 position, Vector2 labelPos, Vector2 wirePosition, bool mouseIn, Wire equippedWire, float wireInterval)
|
||||
{
|
||||
//spriteBatch.DrawString(GUI.SmallFont, Name, new Vector2(labelPos.X, labelPos.Y-10), Color.White);
|
||||
GUI.DrawString(spriteBatch, labelPos, Name, IsPower ? Color.Red : Color.White, Color.Black, 0, GUI.SmallFont);
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)position.X - 10, (int)position.Y - 10, 20, 20), Color.White);
|
||||
spriteBatch.Draw(panelTexture, position - new Vector2(16.0f, 16.0f), new Rectangle(64, 256, 32, 32), Color.White);
|
||||
|
||||
connectionSprite.Draw(spriteBatch, position);
|
||||
|
||||
for (int i = 0; i < MaxLinked; i++)
|
||||
{
|
||||
if (Wires[i] == null || Wires[i].Hidden || draggingConnected == Wires[i]) continue;
|
||||
if (wires[i] == null || wires[i].Hidden || draggingConnected == wires[i]) continue;
|
||||
|
||||
Connection recipient = Wires[i].OtherConnection(this);
|
||||
|
||||
DrawWire(spriteBatch, Wires[i], (recipient == null) ? Wires[i].Item : recipient.item, position, wirePosition, mouseIn, equippedWire, panel);
|
||||
Connection recipient = wires[i].OtherConnection(this);
|
||||
|
||||
string label = recipient == null ? "" :
|
||||
wires[i].Locked ? recipient.item.Name + "\n" + TextManager.Get("ConnectionLocked") : recipient.item.Name;
|
||||
DrawWire(spriteBatch, wires[i], (recipient == null) ? wires[i].Item : recipient.item, position, wirePosition, mouseIn, equippedWire, panel, label);
|
||||
|
||||
wirePosition.Y += wireInterval;
|
||||
}
|
||||
|
||||
if (draggingConnected != null && Vector2.Distance(position, PlayerInput.MousePosition) < 13.0f)
|
||||
{
|
||||
spriteBatch.Draw(panelTexture, position - new Vector2(21.5f, 21.5f), new Rectangle(106, 250, 43, 43), Color.White);
|
||||
connectionSpriteHighlight.Draw(spriteBatch, position);
|
||||
|
||||
if (!PlayerInput.LeftButtonHeld())
|
||||
{
|
||||
//find an empty cell for the new connection
|
||||
int index = FindWireIndex(null);
|
||||
|
||||
int index = FindEmptyIndex();
|
||||
if (index > -1 && !Wires.Contains(draggingConnected))
|
||||
{
|
||||
bool alreadyConnected = draggingConnected.IsConnectedTo(panel.Item);
|
||||
@@ -186,22 +184,20 @@ namespace Barotrauma.Items.Components
|
||||
Item.Name + " (" + Name + ") to " + otherConnection.item.Name + " (" + otherConnection.Name + ")", ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
|
||||
AddLink(index, draggingConnected);
|
||||
SetWire(index, draggingConnected);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int screwIndex = (position.Y % 60 < 30) ? 0 : 1;
|
||||
|
||||
|
||||
if (Wires.Any(w => w != null && w != draggingConnected))
|
||||
{
|
||||
spriteBatch.Draw(panelTexture, position - new Vector2(16.0f, 16.0f), new Rectangle(screwIndex * 32, 256, 32, 32), Color.White);
|
||||
int screwIndex = (int)Math.Floor(position.Y / 30.0f) % screwSprites.Count;
|
||||
screwSprites[screwIndex].Draw(spriteBatch, position);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void DrawWire(SpriteBatch spriteBatch, Wire wire, Item item, Vector2 end, Vector2 start, bool mouseIn, Wire equippedWire, ConnectionPanel panel)
|
||||
|
||||
private static void DrawWire(SpriteBatch spriteBatch, Wire wire, Item item, Vector2 end, Vector2 start, bool mouseIn, Wire equippedWire, ConnectionPanel panel, string label)
|
||||
{
|
||||
if (draggingConnected == wire)
|
||||
{
|
||||
@@ -228,13 +224,14 @@ namespace Barotrauma.Items.Components
|
||||
Vector2.Distance(end, PlayerInput.MousePosition) < 20.0f ||
|
||||
new Rectangle((start.X < end.X) ? textX - 100 : textX, (int)start.Y - 5, 100, 14).Contains(PlayerInput.MousePosition));
|
||||
|
||||
string label = wire.Locked || panel.Locked ? item.Name + "\n" + TextManager.Get("ConnectionLocked") : item.Name;
|
||||
|
||||
GUI.DrawString(spriteBatch,
|
||||
new Vector2(start.X < end.X ? textX - GUI.SmallFont.MeasureString(label).X : textX, start.Y - 5.0f),
|
||||
label,
|
||||
(mouseOn ? Color.Gold : Color.White) * (wire.Locked ? 0.6f : 1.0f), Color.Black * 0.8f,
|
||||
3, GUI.SmallFont);
|
||||
if (!string.IsNullOrEmpty(label))
|
||||
{
|
||||
GUI.DrawString(spriteBatch,
|
||||
new Vector2(start.X < end.X ? textX - GUI.SmallFont.MeasureString(label).X : textX, start.Y - 5.0f),
|
||||
label,
|
||||
(mouseOn ? Color.Gold : Color.White) * (wire.Locked ? 0.6f : 1.0f), Color.Black * 0.8f,
|
||||
3, GUI.SmallFont);
|
||||
}
|
||||
|
||||
var wireEnd = end + Vector2.Normalize(start - end) * 30.0f;
|
||||
|
||||
|
||||
@@ -1,15 +1,44 @@
|
||||
using Barotrauma.Networking;
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class ConnectionPanel : ItemComponent, IServerSerializable, IClientSerializable
|
||||
{
|
||||
public override void UpdateHUD(Character character)
|
||||
public static Wire HighlightedWire;
|
||||
|
||||
partial void InitProjSpecific(XElement element)
|
||||
{
|
||||
if (GuiFrame == null) return;
|
||||
new GUICustomComponent(new RectTransform(Vector2.One, GuiFrame.RectTransform), DrawConnections, null)
|
||||
{
|
||||
UserData = this
|
||||
};
|
||||
}
|
||||
|
||||
public override void Move(Vector2 amount)
|
||||
{
|
||||
if (item.Submarine == null || item.Submarine.Loading || Screen.Selected != GameMain.SubEditorScreen) return;
|
||||
MoveConnectedWires(amount);
|
||||
}
|
||||
|
||||
public override bool ShouldDrawHUD(Character character)
|
||||
{
|
||||
return character == Character.Controlled && character == user;
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
{
|
||||
GuiFrame?.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
||||
{
|
||||
if (character != Character.Controlled || character != user) return;
|
||||
|
||||
@@ -21,12 +50,17 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
private void DrawConnections(SpriteBatch spriteBatch, GUICustomComponent container)
|
||||
{
|
||||
if (character != Character.Controlled || character != user) return;
|
||||
if (user != Character.Controlled || user == null) return;
|
||||
|
||||
HighlightedWire = null;
|
||||
Connection.DrawConnections(spriteBatch, this, character);
|
||||
Connection.DrawConnections(spriteBatch, this, user);
|
||||
|
||||
foreach (UISprite sprite in GUI.Style.GetComponentStyle("ConnectionPanelFront").Sprites[GUIComponent.ComponentState.None])
|
||||
{
|
||||
sprite.Draw(spriteBatch, GuiFrame.Rect, Color.White, SpriteEffects.None);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +81,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private void ApplyRemoteState(NetBuffer msg)
|
||||
{
|
||||
List<Wire> prevWires = Connections.SelectMany(c => Array.FindAll(c.Wires, w => w != null)).ToList();
|
||||
List<Wire> prevWires = Connections.SelectMany(c => c.Wires.Where(w => w != null)).ToList();
|
||||
List<Wire> newWires = new List<Wire>();
|
||||
|
||||
foreach (Connection connection in Connections)
|
||||
@@ -69,7 +103,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
newWires.Add(wireComponent);
|
||||
|
||||
connection.Wires[i] = wireComponent;
|
||||
connection.SetWire(i, wireComponent);
|
||||
wireComponent.Connect(connection, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
using Barotrauma.Networking;
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class CustomInterface
|
||||
{
|
||||
private List<GUIComponent> uiElements = new List<GUIComponent>();
|
||||
|
||||
partial void InitProjSpecific(XElement element)
|
||||
{
|
||||
uiElements.Clear();
|
||||
|
||||
GUILayoutGroup paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.8f), GuiFrame.RectTransform, Anchor.Center))
|
||||
{ RelativeSpacing = 0.05f, Stretch = true };
|
||||
|
||||
foreach (CustomInterfaceElement ciElement in customInterfaceElementList)
|
||||
{
|
||||
if (ciElement.ContinuousSignal)
|
||||
{
|
||||
var tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), paddedFrame.RectTransform), ciElement.Label)
|
||||
{
|
||||
UserData = ciElement
|
||||
};
|
||||
tickBox.OnSelected += (tBox) =>
|
||||
{
|
||||
if (GameMain.Client == null)
|
||||
{
|
||||
TickBoxToggled(tBox.UserData as CustomInterfaceElement, tBox.Selected);
|
||||
}
|
||||
else
|
||||
{
|
||||
item.CreateClientEvent(this);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
uiElements.Add(tickBox);
|
||||
}
|
||||
else
|
||||
{
|
||||
var btn = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), paddedFrame.RectTransform), ciElement.Label)
|
||||
{
|
||||
UserData = ciElement
|
||||
};
|
||||
btn.OnClicked += (_, userdata) =>
|
||||
{
|
||||
if (GameMain.Client == null)
|
||||
{
|
||||
ButtonClicked(userdata as CustomInterfaceElement);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.Client.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ComponentState, item.components.IndexOf(this), userdata as CustomInterfaceElement });
|
||||
}
|
||||
return true;
|
||||
};
|
||||
uiElements.Add(btn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
partial void UpdateLabelsProjSpecific()
|
||||
{
|
||||
for (int i = 0; i < labels.Length && i < uiElements.Count; i++)
|
||||
{
|
||||
if (uiElements[i] is GUIButton button)
|
||||
{
|
||||
button.Text = labels[i];
|
||||
}
|
||||
else if (uiElements[i] is GUITickBox tickBox)
|
||||
{
|
||||
tickBox.Text = labels[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientWrite(NetBuffer msg, object[] extraData = null)
|
||||
{
|
||||
//extradata contains an array of buttons clicked by the player (or nothing if the player didn't click anything)
|
||||
for (int i = 0; i < customInterfaceElementList.Count; i++)
|
||||
{
|
||||
if (customInterfaceElementList[i].ContinuousSignal)
|
||||
{
|
||||
msg.Write(((GUITickBox)uiElements[i]).Selected);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.Write(extraData != null && extraData.Any(d => d as CustomInterfaceElement == customInterfaceElementList[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
|
||||
{
|
||||
for (int i = 0; i < customInterfaceElementList.Count; i++)
|
||||
{
|
||||
bool elementState = msg.ReadBoolean();
|
||||
if (customInterfaceElementList[i].ContinuousSignal)
|
||||
{
|
||||
((GUITickBox)uiElements[i]).Selected = elementState;
|
||||
TickBoxToggled(customInterfaceElementList[i], elementState);
|
||||
}
|
||||
else if (elementState)
|
||||
{
|
||||
ButtonClicked(customInterfaceElementList[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class MotionSensor : IDrawableComponent
|
||||
{
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing)
|
||||
{
|
||||
if (!editing || !MapEntity.SelectedList.Contains(item)) return;
|
||||
|
||||
Vector2 pos = item.WorldPosition + detectOffset;
|
||||
pos.Y = -pos.Y;
|
||||
GUI.DrawRectangle(spriteBatch, pos - new Vector2(rangeX, rangeY), new Vector2(rangeX, rangeY) * 2.0f, Color.Cyan * 0.5f, isFilled: false, thickness: 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class WifiComponent : IDrawableComponent
|
||||
{
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing)
|
||||
{
|
||||
if (!editing || !MapEntity.SelectedList.Contains(item)) return;
|
||||
|
||||
Vector2 pos = new Vector2(item.DrawPosition.X, -item.DrawPosition.Y);
|
||||
ShapeExtensions.DrawLine(spriteBatch, pos + Vector2.UnitY * range, pos - Vector2.UnitY * range, Color.Cyan * 0.5f, 2);
|
||||
ShapeExtensions.DrawLine(spriteBatch, pos + Vector2.UnitX * range, pos - Vector2.UnitX * range, Color.Cyan * 0.5f, 2);
|
||||
ShapeExtensions.DrawCircle(spriteBatch, pos, range, 32, Color.Cyan * 0.5f, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,8 +35,7 @@ namespace Barotrauma.Items.Components
|
||||
SpriteEffects.None,
|
||||
depth);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private static Sprite wireSprite;
|
||||
|
||||
private static Wire draggingWire;
|
||||
@@ -45,7 +44,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing)
|
||||
{
|
||||
if (sections.Count == 0 && !IsActive)
|
||||
if (sections.Count == 0 && !IsActive || Hidden)
|
||||
{
|
||||
Drawable = false;
|
||||
return;
|
||||
@@ -187,8 +186,7 @@ namespace Barotrauma.Items.Components
|
||||
else
|
||||
{
|
||||
//check if close enough to a node
|
||||
float temp = 0.0f;
|
||||
int closestIndex = selectedWire.GetClosestNodeIndex(mousePos, nodeSelectDist, out temp);
|
||||
int closestIndex = selectedWire.GetClosestNodeIndex(mousePos, nodeSelectDist, out _);
|
||||
if (closestIndex > -1)
|
||||
{
|
||||
highlightedNodeIndex = closestIndex;
|
||||
@@ -209,37 +207,40 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
//check which wire is highlighted with the cursor
|
||||
Wire highlighted = null;
|
||||
float closestDist = float.PositiveInfinity;
|
||||
foreach (Wire w in wires)
|
||||
|
||||
//check which wire is highlighted with the cursor
|
||||
if (GUI.MouseOn == null)
|
||||
{
|
||||
Vector2 mousePos = GameMain.SubEditorScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||
if (w.item.Submarine != null) mousePos -= (w.item.Submarine.Position + w.item.Submarine.HiddenSubPosition);
|
||||
|
||||
float dist = 0.0f;
|
||||
int highlightedNode = w.GetClosestNodeIndex(mousePos, highlighted == null ? nodeSelectDist : closestDist, out dist);
|
||||
if (highlightedNode > -1)
|
||||
float closestDist = float.PositiveInfinity;
|
||||
foreach (Wire w in wires)
|
||||
{
|
||||
if (dist < closestDist)
|
||||
Vector2 mousePos = GameMain.SubEditorScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||
if (w.item.Submarine != null) mousePos -= (w.item.Submarine.Position + w.item.Submarine.HiddenSubPosition);
|
||||
|
||||
int highlightedNode = w.GetClosestNodeIndex(mousePos, highlighted == null ? nodeSelectDist : closestDist, out float dist);
|
||||
if (highlightedNode > -1)
|
||||
{
|
||||
highlightedNodeIndex = highlightedNode;
|
||||
highlighted = w;
|
||||
closestDist = dist;
|
||||
if (dist < closestDist)
|
||||
{
|
||||
highlightedNodeIndex = highlightedNode;
|
||||
highlighted = w;
|
||||
closestDist = dist;
|
||||
}
|
||||
}
|
||||
|
||||
if (w.GetClosestSectionIndex(mousePos, highlighted == null ? sectionSelectDist : closestDist, out dist) > -1)
|
||||
{
|
||||
//prefer nodes over sections
|
||||
if (dist + nodeSelectDist * 0.5f < closestDist)
|
||||
{
|
||||
highlightedNodeIndex = null;
|
||||
highlighted = w;
|
||||
closestDist = dist + nodeSelectDist * 0.5f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (w.GetClosestSectionIndex(mousePos, highlighted == null ? sectionSelectDist : closestDist, out dist) > -1)
|
||||
{
|
||||
//prefer nodes over sections
|
||||
if (dist + nodeSelectDist * 0.5f < closestDist)
|
||||
{
|
||||
highlightedNodeIndex = null;
|
||||
highlighted = w;
|
||||
closestDist = dist + nodeSelectDist * 0.5f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (highlighted != null)
|
||||
{
|
||||
|
||||
@@ -137,53 +137,77 @@ namespace Barotrauma.Items.Components
|
||||
hudPos += Vector2.UnitX * 50.0f;
|
||||
|
||||
List<string> texts = new List<string>();
|
||||
List<Color> textColors = new List<Color>();
|
||||
|
||||
if (target.Info != null)
|
||||
{
|
||||
texts.Add(target.Name);
|
||||
textColors.Add(Color.White);
|
||||
}
|
||||
|
||||
|
||||
if (target.IsDead)
|
||||
{
|
||||
texts.Add(TextManager.Get("Deceased"));
|
||||
texts.Add(TextManager.Get("CauseOfDeath") + ": " + TextManager.Get("CauseOfDeath." + target.CauseOfDeath.ToString()));
|
||||
textColors.Add(Color.Red);
|
||||
texts.Add(
|
||||
target.CauseOfDeath.Affliction?.CauseOfDeathDescription ??
|
||||
TextManager.Get("CauseOfDeath") + ": " +TextManager.Get("CauseOfDeath." + target.CauseOfDeath.Type.ToString()));
|
||||
textColors.Add(Color.Red);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (target.IsUnconscious) texts.Add(TextManager.Get("Unconscious"));
|
||||
if (target.Stun > 0.01f) texts.Add(TextManager.Get("Stunned"));
|
||||
|
||||
int healthTextIndex = target.Health > 95.0f ? 0 :
|
||||
MathHelper.Clamp((int)Math.Ceiling((1.0f - (target.Health / 200.0f + 0.5f)) * HealthTexts.Length), 0, HealthTexts.Length - 1);
|
||||
|
||||
texts.Add(HealthTexts[healthTextIndex]);
|
||||
|
||||
if (target.IsUnconscious)
|
||||
{
|
||||
texts.Add(TextManager.Get("Unconscious"));
|
||||
textColors.Add(Color.Orange);
|
||||
}
|
||||
if (target.Stun > 0.01f)
|
||||
{
|
||||
texts.Add(TextManager.Get("Stunned"));
|
||||
textColors.Add(Color.Orange);
|
||||
}
|
||||
|
||||
int oxygenTextIndex = MathHelper.Clamp((int)Math.Floor((1.0f - (target.Oxygen / 100.0f)) * OxygenTexts.Length), 0, OxygenTexts.Length - 1);
|
||||
texts.Add(OxygenTexts[oxygenTextIndex]);
|
||||
textColors.Add(Color.Lerp(Color.Red, Color.Green, target.Oxygen / 100.0f));
|
||||
|
||||
if (target.Bleeding > 0.0f)
|
||||
{
|
||||
int bleedingTextIndex = MathHelper.Clamp((int)Math.Floor(target.Bleeding / 4.0f) * BleedingTexts.Length, 0, BleedingTexts.Length - 1);
|
||||
int bleedingTextIndex = MathHelper.Clamp((int)Math.Floor(target.Bleeding / 100.0f) * BleedingTexts.Length, 0, BleedingTexts.Length - 1);
|
||||
texts.Add(BleedingTexts[bleedingTextIndex]);
|
||||
textColors.Add(Color.Lerp(Color.Red, Color.Green, target.Bleeding / 100.0f));
|
||||
}
|
||||
|
||||
if (target.huskInfection != null)
|
||||
var allAfflictions = target.CharacterHealth.GetAllAfflictions();
|
||||
Dictionary<AfflictionPrefab, float> combinedAfflictionStrengths = new Dictionary<AfflictionPrefab, float>();
|
||||
foreach (Affliction affliction in allAfflictions)
|
||||
{
|
||||
if (target.huskInfection.State == HuskInfection.InfectionState.Transition)
|
||||
if (affliction.Strength < affliction.Prefab.ActivationThreshold || affliction.Strength < affliction.Prefab.ShowIconThreshold) continue;
|
||||
if (combinedAfflictionStrengths.ContainsKey(affliction.Prefab))
|
||||
{
|
||||
texts.Add(TextManager.Get("HuskInfectionTransition"));
|
||||
combinedAfflictionStrengths[affliction.Prefab] += affliction.Strength;
|
||||
}
|
||||
else if (target.huskInfection.State == HuskInfection.InfectionState.Active)
|
||||
else
|
||||
{
|
||||
texts.Add(TextManager.Get("HuskInfectionActive"));
|
||||
combinedAfflictionStrengths[affliction.Prefab] = affliction.Strength;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (AfflictionPrefab affliction in combinedAfflictionStrengths.Keys)
|
||||
{
|
||||
texts.Add(affliction.Name + ": " + ((int)combinedAfflictionStrengths[affliction]).ToString() + " %");
|
||||
textColors.Add(Color.Lerp(Color.Red, Color.Green, combinedAfflictionStrengths[affliction] / affliction.MaxStrength));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (string text in texts)
|
||||
GUI.DrawString(spriteBatch, hudPos, texts[0], textColors[0] * alpha, Color.Black * 0.7f * alpha, 2);
|
||||
hudPos.X += 5.0f;
|
||||
hudPos.Y += 24.0f;
|
||||
|
||||
for (int i = 1; i < texts.Count; i++)
|
||||
{
|
||||
GUI.DrawString(spriteBatch, hudPos, text, Color.LightGreen * alpha, Color.Black * 0.7f * alpha, 2);
|
||||
hudPos.Y += 24.0f;
|
||||
GUI.DrawString(spriteBatch, hudPos, texts[i], textColors[i] * alpha, Color.Black * 0.7f * alpha, 2, GUI.SmallFont);
|
||||
hudPos.Y += 18.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Barotrauma.Networking;
|
||||
using Barotrauma.Particles;
|
||||
using Barotrauma.Sounds;
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
@@ -12,10 +14,25 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class Turret : Powered, IDrawableComponent, IServerSerializable
|
||||
{
|
||||
private Sprite crosshairSprite, disabledCrossHairSprite;
|
||||
private Sprite crosshairSprite, crosshairPointerSprite;
|
||||
|
||||
private GUIProgressBar powerIndicator;
|
||||
|
||||
private float recoilTimer;
|
||||
|
||||
private RoundSound startMoveSound, endMoveSound, moveSound;
|
||||
|
||||
private SoundChannel moveSoundChannel;
|
||||
|
||||
private Vector2 crosshairPos, crosshairPointerPos;
|
||||
|
||||
private bool flashLowPower;
|
||||
private bool flashNoAmmo;
|
||||
private float flashTimer;
|
||||
private float flashLength = 1;
|
||||
|
||||
private List<ParticleEmitter> particleEmitters = new List<ParticleEmitter>();
|
||||
|
||||
[Editable, Serialize("0.0,0.0,0.0,0.0", true)]
|
||||
public Color HudTint
|
||||
{
|
||||
@@ -37,6 +54,13 @@ namespace Barotrauma.Items.Components
|
||||
private set;
|
||||
}
|
||||
|
||||
[Serialize(0.0f, false)]
|
||||
public float RecoilDistance
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
partial void InitProjSpecific(XElement element)
|
||||
{
|
||||
foreach (XElement subElement in element.Elements())
|
||||
@@ -47,77 +71,220 @@ namespace Barotrauma.Items.Components
|
||||
case "crosshair":
|
||||
crosshairSprite = new Sprite(subElement, texturePath.Contains("/") ? "" : Path.GetDirectoryName(item.Prefab.ConfigFile));
|
||||
break;
|
||||
case "disabledcrosshair":
|
||||
disabledCrossHairSprite = new Sprite(subElement, texturePath.Contains("/") ? "" : Path.GetDirectoryName(item.Prefab.ConfigFile));
|
||||
case "crosshairpointer":
|
||||
crosshairPointerSprite = new Sprite(subElement, texturePath.Contains("/") ? "" : Path.GetDirectoryName(item.Prefab.ConfigFile));
|
||||
break;
|
||||
case "startmovesound":
|
||||
startMoveSound = Submarine.LoadRoundSound(subElement, false);
|
||||
break;
|
||||
case "endmovesound":
|
||||
endMoveSound = Submarine.LoadRoundSound(subElement, false);
|
||||
break;
|
||||
case "movesound":
|
||||
moveSound = Submarine.LoadRoundSound(subElement, false);
|
||||
break;
|
||||
case "particleemitter":
|
||||
particleEmitters.Add(new ParticleEmitter(subElement));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int barWidth = 200;
|
||||
powerIndicator = new GUIProgressBar(new Rectangle(GameMain.GraphicsWidth / 2 - barWidth / 2, 20, barWidth, 30), Color.White, 0.0f);
|
||||
|
||||
powerIndicator = new GUIProgressBar(new RectTransform(new Vector2(0.18f, 0.03f), GUI.Canvas, Anchor.TopCenter)
|
||||
{
|
||||
MinSize = new Point(100,20),
|
||||
RelativeOffset = new Vector2(0.0f, 0.01f)
|
||||
},
|
||||
barSize: 0.0f);
|
||||
}
|
||||
|
||||
|
||||
partial void LaunchProjSpecific()
|
||||
{
|
||||
recoilTimer = Math.Max(Reload, 0.1f);
|
||||
PlaySound(ActionType.OnUse, item.WorldPosition);
|
||||
Vector2 particlePos = new Vector2(item.WorldRect.X + transformedBarrelPos.X, item.WorldRect.Y - transformedBarrelPos.Y);
|
||||
foreach (ParticleEmitter emitter in particleEmitters)
|
||||
{
|
||||
emitter.Emit(1.0f, particlePos, hullGuess: null, angle: rotation, particleRotation: rotation);
|
||||
}
|
||||
}
|
||||
|
||||
partial void UpdateProjSpecific(float deltaTime)
|
||||
{
|
||||
recoilTimer -= deltaTime;
|
||||
|
||||
if (crosshairSprite != null)
|
||||
{
|
||||
Vector2 itemPos = cam.WorldToScreen(new Vector2(item.WorldRect.X + transformedBarrelPos.X, item.WorldRect.Y - transformedBarrelPos.Y));
|
||||
Vector2 turretDir = new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation));
|
||||
|
||||
Vector2 mouseDiff = itemPos - PlayerInput.MousePosition;
|
||||
crosshairPos = new Vector2(
|
||||
MathHelper.Clamp(itemPos.X + turretDir.X * mouseDiff.Length(), 0, GameMain.GraphicsWidth),
|
||||
MathHelper.Clamp(itemPos.Y + turretDir.Y * mouseDiff.Length(), 0, GameMain.GraphicsHeight));
|
||||
}
|
||||
|
||||
crosshairPointerPos = PlayerInput.MousePosition;
|
||||
|
||||
if (Math.Abs(angularVelocity) > 0.1f)
|
||||
{
|
||||
if (moveSoundChannel == null && startMoveSound != null)
|
||||
{
|
||||
moveSoundChannel = SoundPlayer.PlaySound(startMoveSound.Sound, startMoveSound.Volume, startMoveSound.Range, item.WorldPosition);
|
||||
}
|
||||
else if (moveSoundChannel == null || !moveSoundChannel.IsPlaying)
|
||||
{
|
||||
if (moveSound != null)
|
||||
{
|
||||
moveSoundChannel.Dispose();
|
||||
moveSoundChannel = SoundPlayer.PlaySound(moveSound.Sound, moveSound.Volume, moveSound.Range, item.WorldPosition);
|
||||
if (moveSoundChannel != null) moveSoundChannel.Looping = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Math.Abs(angularVelocity) < 0.05f)
|
||||
{
|
||||
if (moveSoundChannel != null)
|
||||
{
|
||||
if (endMoveSound != null && moveSoundChannel.Sound != endMoveSound.Sound)
|
||||
{
|
||||
moveSoundChannel.Dispose();
|
||||
moveSoundChannel = SoundPlayer.PlaySound(endMoveSound.Sound, endMoveSound.Volume, endMoveSound.Range, item.WorldPosition);
|
||||
if (moveSoundChannel != null) moveSoundChannel.Looping = false;
|
||||
}
|
||||
else if (!moveSoundChannel.IsPlaying)
|
||||
{
|
||||
moveSoundChannel.Dispose();
|
||||
moveSoundChannel = null;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (moveSoundChannel != null && moveSoundChannel.IsPlaying)
|
||||
{
|
||||
moveSoundChannel.Gain = MathHelper.Clamp(Math.Abs(angularVelocity), 0.5f, 1.0f);
|
||||
}
|
||||
|
||||
if (flashLowPower || flashNoAmmo)
|
||||
{
|
||||
flashTimer += deltaTime;
|
||||
if (flashTimer >= flashLength)
|
||||
{
|
||||
flashTimer = 0;
|
||||
flashLowPower = false;
|
||||
flashNoAmmo = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
||||
{
|
||||
if (crosshairSprite != null)
|
||||
{
|
||||
Vector2 itemPos = cam.WorldToScreen(item.WorldPosition);
|
||||
Vector2 turretDir = new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation));
|
||||
|
||||
Vector2 mouseDiff = itemPos - PlayerInput.MousePosition;
|
||||
crosshairPos = new Vector2(
|
||||
MathHelper.Clamp(itemPos.X + turretDir.X * mouseDiff.Length(), 0, GameMain.GraphicsWidth),
|
||||
MathHelper.Clamp(itemPos.Y + turretDir.Y * mouseDiff.Length(), 0, GameMain.GraphicsHeight));
|
||||
}
|
||||
|
||||
crosshairPointerPos = PlayerInput.MousePosition;
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing = false)
|
||||
{
|
||||
Vector2 drawPos = new Vector2(item.Rect.X, item.Rect.Y);
|
||||
Vector2 drawPos = new Vector2(item.Rect.X + transformedBarrelPos.X, item.Rect.Y - transformedBarrelPos.Y);
|
||||
if (item.Submarine != null) drawPos += item.Submarine.DrawPosition;
|
||||
drawPos.Y = -drawPos.Y;
|
||||
|
||||
if (barrelSprite != null)
|
||||
float recoilOffset = 0.0f;
|
||||
if (RecoilDistance > 0.0f && recoilTimer > 0.0f)
|
||||
{
|
||||
barrelSprite.Draw(spriteBatch,
|
||||
drawPos + barrelPos, Color.White,
|
||||
rotation + MathHelper.PiOver2, 1.0f,
|
||||
SpriteEffects.None, item.Sprite.Depth + 0.01f);
|
||||
//move the barrel backwards 0.1 seconds after launching
|
||||
if (recoilTimer >= Math.Max(Reload, 0.1f) - 0.1f)
|
||||
{
|
||||
recoilOffset = RecoilDistance * (1.0f - (recoilTimer - (Math.Max(Reload, 0.1f) - 0.1f)) / 0.1f);
|
||||
}
|
||||
//move back to normal position while reloading
|
||||
else
|
||||
{
|
||||
recoilOffset = RecoilDistance * recoilTimer / (Math.Max(Reload, 0.1f) - 0.1f);
|
||||
}
|
||||
}
|
||||
|
||||
railSprite?.Draw(spriteBatch,
|
||||
drawPos,
|
||||
Color.White,
|
||||
rotation + MathHelper.PiOver2, item.Scale,
|
||||
SpriteEffects.None, item.SpriteDepth + (railSprite.Depth - item.Sprite.Depth));
|
||||
|
||||
barrelSprite?.Draw(spriteBatch,
|
||||
drawPos - new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation)) * recoilOffset * item.Scale,
|
||||
Color.White,
|
||||
rotation + MathHelper.PiOver2, item.Scale,
|
||||
SpriteEffects.None, item.SpriteDepth + (barrelSprite.Depth - item.Sprite.Depth));
|
||||
|
||||
|
||||
if (!editing) return;
|
||||
|
||||
GUI.DrawLine(spriteBatch,
|
||||
drawPos + barrelPos,
|
||||
drawPos + barrelPos + new Vector2((float)Math.Cos(minRotation), (float)Math.Sin(minRotation)) * 60.0f,
|
||||
drawPos,
|
||||
drawPos + new Vector2((float)Math.Cos(minRotation), (float)Math.Sin(minRotation)) * 60.0f,
|
||||
Color.Green);
|
||||
|
||||
GUI.DrawLine(spriteBatch,
|
||||
drawPos + barrelPos,
|
||||
drawPos + barrelPos + new Vector2((float)Math.Cos(maxRotation), (float)Math.Sin(maxRotation)) * 60.0f,
|
||||
drawPos,
|
||||
drawPos + new Vector2((float)Math.Cos(maxRotation), (float)Math.Sin(maxRotation)) * 60.0f,
|
||||
Color.Green);
|
||||
|
||||
GUI.DrawLine(spriteBatch,
|
||||
drawPos + barrelPos,
|
||||
drawPos + barrelPos + new Vector2((float)Math.Cos((maxRotation + minRotation) / 2), (float)Math.Sin((maxRotation + minRotation) / 2)) * 60.0f,
|
||||
drawPos,
|
||||
drawPos + new Vector2((float)Math.Cos((maxRotation + minRotation) / 2), (float)Math.Sin((maxRotation + minRotation) / 2)) * 60.0f,
|
||||
Color.LightGreen);
|
||||
|
||||
}
|
||||
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
{
|
||||
if (HudTint.A > 0)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight),
|
||||
new Color(HudTint.R, HudTint.G, HudTint.B) * (HudTint.A/255.0f), true);
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight),
|
||||
new Color(HudTint.R, HudTint.G, HudTint.B) * (HudTint.A / 255.0f), true);
|
||||
}
|
||||
|
||||
GetAvailablePower(out float batteryCharge, out float batteryCapacity);
|
||||
|
||||
float batteryCharge;
|
||||
float batteryCapacity;
|
||||
GetAvailablePower(out batteryCharge, out batteryCapacity);
|
||||
|
||||
List<Projectile> projectiles = GetLoadedProjectiles(false, true);
|
||||
List<Item> availableAmmo = new List<Item>();
|
||||
foreach (MapEntity e in item.linkedTo)
|
||||
{
|
||||
var linkedItem = e as Item;
|
||||
if (linkedItem == null) continue;
|
||||
|
||||
var itemContainer = linkedItem.GetComponent<ItemContainer>();
|
||||
if (itemContainer?.Inventory?.Items == null) continue;
|
||||
|
||||
availableAmmo.AddRange(itemContainer.Inventory.Items);
|
||||
}
|
||||
|
||||
float chargeRate = powerConsumption <= 0.0f ? 1.0f : batteryCharge / batteryCapacity;
|
||||
bool charged = batteryCharge * 3600.0f > powerConsumption;
|
||||
bool readyToFire = reload <= 0.0f && charged && projectiles.Any(p => p != null);
|
||||
|
||||
bool readyToFire = reload <= 0.0f && charged && availableAmmo.Any(p => p != null);
|
||||
if (ShowChargeIndicator && PowerConsumption > 0.0f)
|
||||
{
|
||||
powerIndicator.BarSize = chargeRate;
|
||||
powerIndicator.Color = charged ? Color.Green : Color.Red;
|
||||
powerIndicator.Draw(spriteBatch);
|
||||
if (flashLowPower)
|
||||
{
|
||||
powerIndicator.BarSize = 1;
|
||||
powerIndicator.Color *= (float)Math.Sin(flashTimer * 12);
|
||||
powerIndicator.RectTransform.ChangeScale(Vector2.Lerp(Vector2.One, Vector2.One * 1.01f, 2 * (float)Math.Sin(flashTimer * 15)));
|
||||
}
|
||||
else
|
||||
{
|
||||
powerIndicator.BarSize = chargeRate;
|
||||
}
|
||||
powerIndicator.DrawManually(spriteBatch, true);
|
||||
|
||||
int requiredChargeIndicatorPos = (int)((powerConsumption / (batteryCapacity * 3600.0f)) * powerIndicator.Rect.Width);
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
@@ -129,27 +296,33 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
Point slotSize = new Point(60, 30);
|
||||
int spacing = 5;
|
||||
int slotsPerRow = Math.Min(projectiles.Count, 6);
|
||||
int slotsPerRow = Math.Min(availableAmmo.Count, 6);
|
||||
int totalWidth = slotSize.X * slotsPerRow + spacing * (slotsPerRow - 1);
|
||||
Point invSlotPos = new Point(GameMain.GraphicsWidth / 2 - totalWidth / 2, 60);
|
||||
for (int i = 0; i < projectiles.Count; i++)
|
||||
for (int i = 0; i < availableAmmo.Count; i++)
|
||||
{
|
||||
Inventory.DrawSlot(spriteBatch,
|
||||
// TODO: Optimize? Creates multiple new classes per frame?
|
||||
Inventory.DrawSlot(spriteBatch, null,
|
||||
new InventorySlot(new Rectangle(invSlotPos + new Point((i % slotsPerRow) * (slotSize.X + spacing), (int)Math.Floor(i / (float)slotsPerRow) * (slotSize.Y + spacing)), slotSize)),
|
||||
projectiles[i] == null ? null : projectiles[i].Item, true);
|
||||
availableAmmo[i], true);
|
||||
}
|
||||
if (flashNoAmmo)
|
||||
{
|
||||
Rectangle rect = new Rectangle(invSlotPos.X, invSlotPos.Y, totalWidth, slotSize.Y);
|
||||
float inflate = MathHelper.Lerp(3, 8, (float)Math.Abs(1 * Math.Sin(flashTimer * 5)));
|
||||
rect.Inflate(inflate, inflate);
|
||||
Color color = Color.Red * MathHelper.Max(0.5f, (float)Math.Sin(flashTimer * 12));
|
||||
GUI.DrawRectangle(spriteBatch, rect, color, thickness: 3);
|
||||
}
|
||||
}
|
||||
|
||||
if (readyToFire)
|
||||
if (crosshairSprite != null)
|
||||
{
|
||||
if (crosshairSprite != null) crosshairSprite.Draw(spriteBatch, PlayerInput.MousePosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (disabledCrossHairSprite != null) disabledCrossHairSprite.Draw(spriteBatch, PlayerInput.MousePosition);
|
||||
crosshairSprite.Draw(spriteBatch, crosshairPos, readyToFire ? Color.White : Color.White * 0.2f, 0, (float)Math.Sqrt(cam.Zoom));
|
||||
}
|
||||
if (crosshairPointerSprite != null) crosshairPointerSprite.Draw(spriteBatch, crosshairPointerPos, 0, (float)Math.Sqrt(cam.Zoom));
|
||||
}
|
||||
|
||||
|
||||
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
|
||||
{
|
||||
UInt16 projectileID = msg.ReadUInt16();
|
||||
|
||||
Reference in New Issue
Block a user