Release v0.15.12.0
This commit is contained in:
@@ -48,8 +48,13 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
color = Color.CornflowerBlue;
|
color = Color.CornflowerBlue;
|
||||||
}
|
}
|
||||||
else if (Entity is Item)
|
else if (Entity is Item i)
|
||||||
{
|
{
|
||||||
|
if (i.Submarine != null && i.GetComponent<Items.Components.Door>() == null)
|
||||||
|
{
|
||||||
|
// Don't show items that are inside the submarine, because monsters shouldn't target them when they are inside and the monsters are outside.
|
||||||
|
return;
|
||||||
|
}
|
||||||
color = Color.CadetBlue;
|
color = Color.CadetBlue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -81,10 +81,10 @@ namespace Barotrauma
|
|||||||
ConvertUnits.ToDisplayUnits(new Vector2(attachJoint.WorldAnchorB.X, -attachJoint.WorldAnchorB.Y)), GUI.Style.Green, 0, 4);
|
ConvertUnits.ToDisplayUnits(new Vector2(attachJoint.WorldAnchorB.X, -attachJoint.WorldAnchorB.Y)), GUI.Style.Green, 0, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LatchOntoAI.WallAttachPos.HasValue)
|
if (LatchOntoAI.AttachPos.HasValue)
|
||||||
{
|
{
|
||||||
//GUI.DrawLine(spriteBatch, pos,
|
GUI.DrawLine(spriteBatch, pos,
|
||||||
// ConvertUnits.ToDisplayUnits(new Vector2(LatchOntoAI.WallAttachPos.Value.X, -LatchOntoAI.WallAttachPos.Value.Y)), GUI.Style.Green, 0, 3);
|
ConvertUnits.ToDisplayUnits(new Vector2(LatchOntoAI.AttachPos.Value.X, -LatchOntoAI.AttachPos.Value.Y)), GUI.Style.Green, 0, 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -284,7 +284,7 @@ namespace Barotrauma
|
|||||||
limb.LastImpactSoundTime = (float)Timing.TotalTime;
|
limb.LastImpactSoundTime = (float)Timing.TotalTime;
|
||||||
if (!string.IsNullOrWhiteSpace(limb.HitSoundTag))
|
if (!string.IsNullOrWhiteSpace(limb.HitSoundTag))
|
||||||
{
|
{
|
||||||
bool inWater = limb.inWater;
|
bool inWater = limb.InWater;
|
||||||
if (character.CurrentHull != null &&
|
if (character.CurrentHull != null &&
|
||||||
character.CurrentHull.Surface > character.CurrentHull.Rect.Y - character.CurrentHull.Rect.Height + 5.0f &&
|
character.CurrentHull.Surface > character.CurrentHull.Rect.Y - character.CurrentHull.Rect.Height + 5.0f &&
|
||||||
limb.SimPosition.Y < ConvertUnits.ToSimUnits(character.CurrentHull.Rect.Y - character.CurrentHull.Rect.Height) + limb.body.GetMaxExtent())
|
limb.SimPosition.Y < ConvertUnits.ToSimUnits(character.CurrentHull.Rect.Y - character.CurrentHull.Rect.Height) + limb.body.GetMaxExtent())
|
||||||
@@ -342,22 +342,41 @@ namespace Barotrauma
|
|||||||
|
|
||||||
partial void SetupDrawOrder()
|
partial void SetupDrawOrder()
|
||||||
{
|
{
|
||||||
//make sure every character gets drawn at a distinct "layer"
|
//make sure every character gets drawn at a distinct "layer"
|
||||||
//(instead of having some of the limbs appear behind and some in front of other characters)
|
//(instead of having some of the limbs appear behind and some in front of other characters)
|
||||||
float startDepth = 0.1f;
|
float startDepth = 0.1f;
|
||||||
float increment = 0.001f;
|
float increment = 0.001f;
|
||||||
foreach (Character otherCharacter in Character.CharacterList)
|
foreach (Character otherCharacter in Character.CharacterList)
|
||||||
{
|
{
|
||||||
if (otherCharacter == character) continue;
|
if (otherCharacter == character) { continue; }
|
||||||
startDepth += increment;
|
startDepth += increment;
|
||||||
}
|
}
|
||||||
//make sure each limb has a distinct depth value
|
//make sure each limb has a distinct depth value
|
||||||
List<Limb> depthSortedLimbs = Limbs.OrderBy(l => l.ActiveSprite == null ? 0.0f : l.ActiveSprite.Depth).ToList();
|
List<Limb> depthSortedLimbs = Limbs.OrderBy(l => l.DefaultSpriteDepth).ToList();
|
||||||
foreach (Limb limb in Limbs)
|
foreach (Limb limb in Limbs)
|
||||||
{
|
{
|
||||||
if (limb.ActiveSprite != null)
|
var sprite = limb.GetActiveSprite();
|
||||||
limb.ActiveSprite.Depth = startDepth + depthSortedLimbs.IndexOf(limb) * 0.00001f;
|
if (sprite == null) { continue; }
|
||||||
|
sprite.Depth = startDepth + depthSortedLimbs.IndexOf(limb) * 0.00001f;
|
||||||
|
foreach (var conditionalSprite in limb.ConditionalSprites)
|
||||||
|
{
|
||||||
|
if (conditionalSprite.Exclusive)
|
||||||
|
{
|
||||||
|
conditionalSprite.ActiveSprite.Depth = sprite.Depth;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
foreach (Limb limb in Limbs)
|
||||||
|
{
|
||||||
|
if (limb.ActiveSprite == null) { continue; }
|
||||||
|
if (limb.Params.InheritLimbDepth == LimbType.None) { continue; }
|
||||||
|
var matchingLimb = GetLimb(limb.Params.InheritLimbDepth);
|
||||||
|
if (matchingLimb != null)
|
||||||
|
{
|
||||||
|
limb.ActiveSprite.Depth = matchingLimb.ActiveSprite.Depth - 0.0000001f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
depthSortedLimbs.Reverse();
|
depthSortedLimbs.Reverse();
|
||||||
inversedLimbDrawOrder = depthSortedLimbs.ToArray();
|
inversedLimbDrawOrder = depthSortedLimbs.ToArray();
|
||||||
}
|
}
|
||||||
@@ -562,9 +581,16 @@ namespace Barotrauma
|
|||||||
if (this is HumanoidAnimController humanoid)
|
if (this is HumanoidAnimController humanoid)
|
||||||
{
|
{
|
||||||
Vector2 pos = ConvertUnits.ToDisplayUnits(humanoid.RightHandIKPos);
|
Vector2 pos = ConvertUnits.ToDisplayUnits(humanoid.RightHandIKPos);
|
||||||
|
if (humanoid.character.Submarine != null) { pos += humanoid.character.Submarine.Position; }
|
||||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 4, 4), GUI.Style.Green, true);
|
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 4, 4), GUI.Style.Green, true);
|
||||||
pos = ConvertUnits.ToDisplayUnits(humanoid.LeftHandIKPos);
|
pos = ConvertUnits.ToDisplayUnits(humanoid.LeftHandIKPos);
|
||||||
|
if (humanoid.character.Submarine != null) { pos += humanoid.character.Submarine.Position; }
|
||||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 4, 4), GUI.Style.Green, true);
|
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 4, 4), GUI.Style.Green, true);
|
||||||
|
|
||||||
|
Vector2 aimPos = humanoid.AimSourceWorldPos;
|
||||||
|
aimPos.Y = -aimPos.Y;
|
||||||
|
GUI.DrawLine(spriteBatch, aimPos - Vector2.UnitY * 3, aimPos + Vector2.UnitY * 3, Color.Red);
|
||||||
|
GUI.DrawLine(spriteBatch, aimPos - Vector2.UnitX * 3, aimPos + Vector2.UnitX * 3, Color.Red);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (character.MemState.Count > 1)
|
if (character.MemState.Count > 1)
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Barotrauma.Sounds;
|
using Barotrauma.Particles;
|
||||||
using Barotrauma.Particles;
|
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ namespace Barotrauma
|
|||||||
public static bool DebugDrawInteract;
|
public static bool DebugDrawInteract;
|
||||||
|
|
||||||
protected float soundTimer;
|
protected float soundTimer;
|
||||||
protected float soundInterval;
|
|
||||||
protected float hudInfoTimer = 1.0f;
|
protected float hudInfoTimer = 1.0f;
|
||||||
protected bool hudInfoVisible = false;
|
protected bool hudInfoVisible = false;
|
||||||
|
|
||||||
@@ -129,8 +128,52 @@ namespace Barotrauma
|
|||||||
get { return gibEmitters; }
|
get { return gibEmitters; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class GUIMessage
|
||||||
|
{
|
||||||
|
public string RawText;
|
||||||
|
public string Identifier;
|
||||||
|
public string Text;
|
||||||
|
|
||||||
|
private int _value;
|
||||||
|
public int Value
|
||||||
|
{
|
||||||
|
get { return _value; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_value = value;
|
||||||
|
Text = RawText.Replace("[value]", _value.ToString());
|
||||||
|
Size = GUI.Font.MeasureString(Text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color Color;
|
||||||
|
public float Lifetime;
|
||||||
|
public float Timer;
|
||||||
|
|
||||||
|
public Vector2 Size;
|
||||||
|
|
||||||
|
public bool PlaySound;
|
||||||
|
|
||||||
|
public GUIMessage(string rawText, Color color, float delay, string identifier = null, int? value = null)
|
||||||
|
{
|
||||||
|
RawText = Text = rawText;
|
||||||
|
if (value.HasValue)
|
||||||
|
{
|
||||||
|
Text = rawText.Replace("[value]", value.Value.ToString());
|
||||||
|
Value = value.Value;
|
||||||
|
}
|
||||||
|
Timer = -delay;
|
||||||
|
Size = GUI.Font.MeasureString(Text);
|
||||||
|
Color = color;
|
||||||
|
Identifier = identifier;
|
||||||
|
Lifetime = 3.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<GUIMessage> guiMessages = new List<GUIMessage>();
|
||||||
|
|
||||||
public static bool IsMouseOnUI => GUI.MouseOn != null ||
|
public static bool IsMouseOnUI => GUI.MouseOn != null ||
|
||||||
(CharacterInventory.IsMouseOnInventory() && !CharacterInventory.DraggingItemToWorld);
|
(CharacterInventory.IsMouseOnInventory && !CharacterInventory.DraggingItemToWorld);
|
||||||
|
|
||||||
public class ObjectiveEntity
|
public class ObjectiveEntity
|
||||||
{
|
{
|
||||||
@@ -161,8 +204,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
partial void InitProjSpecific(XElement mainElement)
|
partial void InitProjSpecific(XElement mainElement)
|
||||||
{
|
{
|
||||||
soundInterval = mainElement.GetAttributeFloat("soundinterval", 10.0f);
|
soundTimer = Rand.Range(0.0f, Params.SoundInterval);
|
||||||
soundTimer = Rand.Range(0.0f, soundInterval);
|
|
||||||
|
|
||||||
sounds = new List<CharacterSound>();
|
sounds = new List<CharacterSound>();
|
||||||
Params.Sounds.ForEach(s => sounds.Add(new CharacterSound(s)));
|
Params.Sounds.ForEach(s => sounds.Add(new CharacterSound(s)));
|
||||||
@@ -390,12 +432,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (attackResult.Damage <= 1.0f) { return; }
|
if (attackResult.Damage <= 1.0f) { return; }
|
||||||
}
|
}
|
||||||
|
PlaySound(CharacterSound.SoundType.Damage, maxInterval: 2);
|
||||||
if (soundTimer < soundInterval * 0.5f)
|
|
||||||
{
|
|
||||||
PlaySound(CharacterSound.SoundType.Damage);
|
|
||||||
soundTimer = soundInterval;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void KillProjSpecific(CauseOfDeathType causeOfDeath, Affliction causeOfDeathAffliction, bool log)
|
partial void KillProjSpecific(CauseOfDeathType causeOfDeath, Affliction causeOfDeathAffliction, bool log)
|
||||||
@@ -412,7 +449,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (GameMain.NetworkMember.RespawnManager?.UseRespawnPrompt ?? false)
|
if (GameMain.NetworkMember.RespawnManager?.UseRespawnPrompt ?? false)
|
||||||
{
|
{
|
||||||
CoroutineManager.InvokeAfter(() =>
|
CoroutineManager.Invoke(() =>
|
||||||
{
|
{
|
||||||
if (controlled != null || (!(GameMain.GameSession?.IsRunning ?? false))) { return; }
|
if (controlled != null || (!(GameMain.GameSession?.IsRunning ?? false))) { return; }
|
||||||
var respawnPrompt = new GUIMessageBox(
|
var respawnPrompt = new GUIMessageBox(
|
||||||
@@ -470,9 +507,9 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private List<Item> debugInteractablesInRange = new List<Item>();
|
private readonly List<Item> debugInteractablesInRange = new List<Item>();
|
||||||
private List<Item> debugInteractablesAtCursor = new List<Item>();
|
private readonly List<Item> debugInteractablesAtCursor = new List<Item>();
|
||||||
private List<Pair<Item, float>> debugInteractablesNearCursor = new List<Pair<Item, float>>();
|
private readonly List<(Item item, float dist)> debugInteractablesNearCursor = new List<(Item item, float dist)>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Finds the front (lowest depth) interactable item at a position. "Interactable" in this case means that the character can "reach" the item.
|
/// Finds the front (lowest depth) interactable item at a position. "Interactable" in this case means that the character can "reach" the item.
|
||||||
@@ -568,7 +605,7 @@ namespace Barotrauma
|
|||||||
if (distanceToItem > closestItemDistance) { continue; }
|
if (distanceToItem > closestItemDistance) { continue; }
|
||||||
if (!CanInteractWith(item)) { continue; }
|
if (!CanInteractWith(item)) { continue; }
|
||||||
|
|
||||||
debugInteractablesNearCursor.Add(new Pair<Item, float>(item, 1.0f - distanceToItem / (100.0f * aimAssistModifier)));
|
debugInteractablesNearCursor.Add((item, 1.0f - distanceToItem / (100.0f * aimAssistModifier)));
|
||||||
closestItem = item;
|
closestItem = item;
|
||||||
closestItemDistance = distanceToItem;
|
closestItemDistance = distanceToItem;
|
||||||
}
|
}
|
||||||
@@ -579,31 +616,20 @@ namespace Barotrauma
|
|||||||
private Character FindCharacterAtPosition(Vector2 mouseSimPos, float maxDist = 150.0f)
|
private Character FindCharacterAtPosition(Vector2 mouseSimPos, float maxDist = 150.0f)
|
||||||
{
|
{
|
||||||
Character closestCharacter = null;
|
Character closestCharacter = null;
|
||||||
float closestDist = 0.0f;
|
|
||||||
|
|
||||||
maxDist = ConvertUnits.ToSimUnits(maxDist);
|
maxDist = ConvertUnits.ToSimUnits(maxDist);
|
||||||
|
float closestDist = maxDist * maxDist;
|
||||||
foreach (Character c in CharacterList)
|
foreach (Character c in CharacterList)
|
||||||
{
|
{
|
||||||
if (!CanInteractWith(c, checkVisibility: false) || (c.AnimController?.SimplePhysicsEnabled ?? true)) { continue; }
|
if (!CanInteractWith(c, checkVisibility: false) || (c.AnimController?.SimplePhysicsEnabled ?? true)) { continue; }
|
||||||
|
|
||||||
float dist = Vector2.DistanceSquared(mouseSimPos, c.SimPosition);
|
float dist = Vector2.DistanceSquared(mouseSimPos, c.SimPosition);
|
||||||
if (dist < maxDist * maxDist && (closestCharacter == null || dist < closestDist))
|
if (dist < closestDist ||
|
||||||
|
(c.CampaignInteractionType != CampaignMode.InteractionType.None && closestCharacter?.CampaignInteractionType == CampaignMode.InteractionType.None && dist * 0.9f < closestDist))
|
||||||
{
|
{
|
||||||
closestCharacter = c;
|
closestCharacter = c;
|
||||||
closestDist = dist;
|
closestDist = dist;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*FarseerPhysics.Common.Transform transform;
|
|
||||||
c.AnimController.Collider.FarseerBody.GetTransform(out transform);
|
|
||||||
for (int i = 0; i < c.AnimController.Collider.FarseerBody.FixtureList.Count; i++)
|
|
||||||
{
|
|
||||||
if (c.AnimController.Collider.FarseerBody.FixtureList[i].Shape.TestPoint(ref transform, ref mouseSimPos))
|
|
||||||
{
|
|
||||||
Console.WriteLine("Hit: " + i);
|
|
||||||
closestCharacter = c;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return closestCharacter;
|
return closestCharacter;
|
||||||
@@ -636,9 +662,20 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (GUIMessage message in guiMessages)
|
||||||
|
{
|
||||||
|
bool wasPending = message.Timer < 0.0f;
|
||||||
|
message.Timer += deltaTime;
|
||||||
|
if (wasPending && message.Timer >= 0.0f && message.PlaySound)
|
||||||
|
{
|
||||||
|
SoundPlayer.PlayUISound(GUISoundType.UIMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
guiMessages.RemoveAll(m => m.Timer >= m.Lifetime);
|
||||||
|
|
||||||
if (!enabled) { return; }
|
if (!enabled) { return; }
|
||||||
|
|
||||||
if (!IsDead && !IsIncapacitated)
|
if (!IsIncapacitated)
|
||||||
{
|
{
|
||||||
if (soundTimer > 0)
|
if (soundTimer > 0)
|
||||||
{
|
{
|
||||||
@@ -649,7 +686,14 @@ namespace Barotrauma
|
|||||||
switch (enemyAI.State)
|
switch (enemyAI.State)
|
||||||
{
|
{
|
||||||
case AIState.Attack:
|
case AIState.Attack:
|
||||||
PlaySound(CharacterSound.SoundType.Attack);
|
if (Rand.Value() > 0.5f)
|
||||||
|
{
|
||||||
|
PlaySound(CharacterSound.SoundType.Attack);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PlaySound(CharacterSound.SoundType.Idle);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
var petBehavior = enemyAI.PetBehavior;
|
var petBehavior = enemyAI.PetBehavior;
|
||||||
@@ -660,7 +704,6 @@ namespace Barotrauma
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
PlaySound(CharacterSound.SoundType.Idle);
|
PlaySound(CharacterSound.SoundType.Idle);
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -749,6 +792,27 @@ namespace Barotrauma
|
|||||||
if (drawHealth && !CharacterHUD.IsCampaignInterfaceOpen) { CharacterHealth.DrawHUD(spriteBatch); }
|
if (drawHealth && !CharacterHUD.IsCampaignInterfaceOpen) { CharacterHealth.DrawHUD(spriteBatch); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DrawGUIMessages(SpriteBatch spriteBatch, Camera cam)
|
||||||
|
{
|
||||||
|
if (info == null || !Enabled || InvisibleTimer > 0.0f)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 messagePos = DrawPosition;
|
||||||
|
messagePos.Y += hudInfoHeight;
|
||||||
|
messagePos = cam.WorldToScreen(messagePos) - Vector2.UnitY * GUI.IntScale(60);
|
||||||
|
foreach (GUIMessage message in guiMessages)
|
||||||
|
{
|
||||||
|
if (message.Timer < 0) { continue; }
|
||||||
|
Vector2 drawPos = messagePos + Vector2.UnitX * (GUI.IntScale(60) - message.Size.X);
|
||||||
|
drawPos = new Vector2((int)drawPos.X, (int)drawPos.Y);
|
||||||
|
float alpha = MathHelper.SmoothStep(1.0f, 0.0f, message.Timer / message.Lifetime);
|
||||||
|
GUI.DrawString(spriteBatch, drawPos, message.Text, message.Color * alpha);
|
||||||
|
messagePos -= Vector2.UnitY * message.Size.Y * 1.2f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public virtual void DrawFront(SpriteBatch spriteBatch, Camera cam)
|
public virtual void DrawFront(SpriteBatch spriteBatch, Camera cam)
|
||||||
{
|
{
|
||||||
if (!Enabled || InvisibleTimer > 0.0f || (AnimController?.SimplePhysicsEnabled ?? true)) { return; }
|
if (!Enabled || InvisibleTimer > 0.0f || (AnimController?.SimplePhysicsEnabled ?? true)) { return; }
|
||||||
@@ -827,12 +891,12 @@ namespace Barotrauma
|
|||||||
GUI.DrawLine(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y),
|
GUI.DrawLine(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y),
|
||||||
new Vector2(item.DrawPosition.X, -item.DrawPosition.Y), Color.White * 0.1f, width: 4);
|
new Vector2(item.DrawPosition.X, -item.DrawPosition.Y), Color.White * 0.1f, width: 4);
|
||||||
}
|
}
|
||||||
foreach (Pair<Item, float> item in debugInteractablesNearCursor)
|
foreach ((Item item, float dist) in debugInteractablesNearCursor)
|
||||||
{
|
{
|
||||||
GUI.DrawLine(spriteBatch,
|
GUI.DrawLine(spriteBatch,
|
||||||
cursorPos,
|
cursorPos,
|
||||||
new Vector2(item.First.DrawPosition.X, -item.First.DrawPosition.Y),
|
new Vector2(item.DrawPosition.X, -item.DrawPosition.Y),
|
||||||
ToolBox.GradientLerp(item.Second, GUI.Style.Red, GUI.Style.Orange, GUI.Style.Green), width: 2);
|
ToolBox.GradientLerp(dist, GUI.Style.Red, GUI.Style.Orange, GUI.Style.Green), width: 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -856,6 +920,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
Vector2 nameSize = GUI.Font.MeasureString(name);
|
Vector2 nameSize = GUI.Font.MeasureString(name);
|
||||||
Vector2 namePos = new Vector2(pos.X, pos.Y - 10.0f - (5.0f / cam.Zoom)) - nameSize * 0.5f / cam.Zoom;
|
Vector2 namePos = new Vector2(pos.X, pos.Y - 10.0f - (5.0f / cam.Zoom)) - nameSize * 0.5f / cam.Zoom;
|
||||||
|
Color nameColor = GetNameColor();
|
||||||
|
|
||||||
Vector2 screenSize = new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
Vector2 screenSize = new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||||
Vector2 viewportSize = new Vector2(cam.WorldView.Width, cam.WorldView.Height);
|
Vector2 viewportSize = new Vector2(cam.WorldView.Width, cam.WorldView.Height);
|
||||||
@@ -865,18 +930,6 @@ namespace Barotrauma
|
|||||||
namePos *= viewportSize / screenSize;
|
namePos *= viewportSize / screenSize;
|
||||||
namePos.X += cam.WorldView.X; namePos.Y -= cam.WorldView.Y;
|
namePos.X += cam.WorldView.X; namePos.Y -= cam.WorldView.Y;
|
||||||
|
|
||||||
Color nameColor = Color.White;
|
|
||||||
if (Controlled != null && TeamID != Controlled.TeamID)
|
|
||||||
{
|
|
||||||
if (TeamID == CharacterTeamType.FriendlyNPC)
|
|
||||||
{
|
|
||||||
nameColor = UniqueNameColor ?? Color.SkyBlue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nameColor = GUI.Style.Red;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (CampaignInteractionType != CampaignMode.InteractionType.None && AllowCustomInteract)
|
if (CampaignInteractionType != CampaignMode.InteractionType.None && AllowCustomInteract)
|
||||||
{
|
{
|
||||||
var iconStyle = GUI.Style.GetComponentStyle("CampaignInteractionBubble." + CampaignInteractionType);
|
var iconStyle = GUI.Style.GetComponentStyle("CampaignInteractionBubble." + CampaignInteractionType);
|
||||||
@@ -931,6 +984,89 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Color GetNameColor()
|
||||||
|
{
|
||||||
|
CharacterTeamType team = teamID;
|
||||||
|
if (Info?.IsDisguisedAsAnother != null)
|
||||||
|
{
|
||||||
|
var idCard = Inventory.GetItemInLimbSlot(InvSlotType.Card)?.GetComponent<IdCard>();
|
||||||
|
if (idCard != null)
|
||||||
|
{
|
||||||
|
if (team == CharacterTeamType.Team2 && idCard.TeamID != CharacterTeamType.Team2)
|
||||||
|
{
|
||||||
|
team = CharacterTeamType.Team1;
|
||||||
|
}
|
||||||
|
else if (team == CharacterTeamType.Team1 && idCard.TeamID == CharacterTeamType.Team2)
|
||||||
|
{
|
||||||
|
team = CharacterTeamType.Team2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Color nameColor = GUI.Style.TextColor;
|
||||||
|
if (Controlled != null && team != Controlled.TeamID)
|
||||||
|
{
|
||||||
|
if (TeamID == CharacterTeamType.FriendlyNPC)
|
||||||
|
{
|
||||||
|
nameColor = UniqueNameColor ?? Color.SkyBlue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nameColor = GUI.Style.Red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nameColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddMessage(string rawText, Color color, bool playSound, string identifier = null, int? value = null)
|
||||||
|
{
|
||||||
|
GUIMessage existingMessage = null;
|
||||||
|
|
||||||
|
float delay = 0.0f;
|
||||||
|
if (guiMessages.Any())
|
||||||
|
{
|
||||||
|
delay = guiMessages.Min(m => m.Timer) - 0.5f;
|
||||||
|
if (delay < 0)
|
||||||
|
{
|
||||||
|
delay = -delay;
|
||||||
|
if (guiMessages.Count > 5)
|
||||||
|
{
|
||||||
|
//reduce delays if there's lots of messages
|
||||||
|
guiMessages.Where(m => m.Timer < 0.0f).ForEach(m => m.Timer *= 0.9f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delay = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (identifier != null)
|
||||||
|
{
|
||||||
|
existingMessage = guiMessages.Find(m => m.Identifier == identifier && m.Timer < m.Lifetime * 0.5f);
|
||||||
|
}
|
||||||
|
if (existingMessage == null || !value.HasValue)
|
||||||
|
{
|
||||||
|
var newMessage = new GUIMessage(rawText, color, delay, identifier, value);
|
||||||
|
guiMessages.Insert(0, newMessage);
|
||||||
|
if (playSound)
|
||||||
|
{
|
||||||
|
if (delay > 0.0f)
|
||||||
|
{
|
||||||
|
newMessage.PlaySound = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SoundPlayer.PlayUISound(GUISoundType.UIMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
existingMessage.Value += value.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a progress bar that's "linked" to the specified object (or updates an existing one if there's one already linked to the object)
|
/// Creates a progress bar that's "linked" to the specified object (or updates an existing one if there's one already linked to the object)
|
||||||
/// The progress bar will automatically fade out after 1 sec if the method hasn't been called during that time
|
/// The progress bar will automatically fade out after 1 sec if the method hasn't been called during that time
|
||||||
@@ -958,12 +1094,13 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private readonly List<CharacterSound> matchingSounds = new List<CharacterSound>();
|
private readonly List<CharacterSound> matchingSounds = new List<CharacterSound>();
|
||||||
private SoundChannel soundChannel;
|
private SoundChannel soundChannel;
|
||||||
public void PlaySound(CharacterSound.SoundType soundType, float soundIntervalFactor = 1.0f)
|
public void PlaySound(CharacterSound.SoundType soundType, float soundIntervalFactor = 1.0f, float maxInterval = 0)
|
||||||
{
|
{
|
||||||
if (sounds == null || sounds.Count == 0) { return; }
|
if (sounds == null || sounds.Count == 0) { return; }
|
||||||
if (soundChannel != null && soundChannel.IsPlaying) { return; }
|
if (soundChannel != null && soundChannel.IsPlaying) { return; }
|
||||||
if (GameMain.SoundManager?.Disabled ?? true) { return; }
|
if (GameMain.SoundManager?.Disabled ?? true) { return; }
|
||||||
if (soundTimer > soundInterval * soundIntervalFactor) { return; }
|
if (soundTimer > Params.SoundInterval * soundIntervalFactor) { return; }
|
||||||
|
if (Params.SoundInterval - soundTimer < maxInterval) { return; }
|
||||||
matchingSounds.Clear();
|
matchingSounds.Clear();
|
||||||
foreach (var s in sounds)
|
foreach (var s in sounds)
|
||||||
{
|
{
|
||||||
@@ -975,7 +1112,7 @@ namespace Barotrauma
|
|||||||
var selectedSound = matchingSounds.GetRandom();
|
var selectedSound = matchingSounds.GetRandom();
|
||||||
if (selectedSound?.Sound == null) { return; }
|
if (selectedSound?.Sound == null) { return; }
|
||||||
soundChannel = SoundPlayer.PlaySound(selectedSound.Sound, AnimController.WorldPosition, selectedSound.Volume, selectedSound.Range, hullGuess: CurrentHull, ignoreMuffling: selectedSound.IgnoreMuffling);
|
soundChannel = SoundPlayer.PlaySound(selectedSound.Sound, AnimController.WorldPosition, selectedSound.Volume, selectedSound.Range, hullGuess: CurrentHull, ignoreMuffling: selectedSound.IgnoreMuffling);
|
||||||
soundTimer = soundInterval;
|
soundTimer = Params.SoundInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddActiveObjectiveEntity(Entity entity, Sprite sprite, Color? color = null)
|
public void AddActiveObjectiveEntity(Entity entity, Sprite sprite, Color? color = null)
|
||||||
@@ -1028,5 +1165,20 @@ namespace Barotrauma
|
|||||||
Rand.Range(50.0f, 500.0f), null);
|
Rand.Range(50.0f, 500.0f), null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
partial void OnMoneyChanged(int prevAmount, int newAmount)
|
||||||
|
{
|
||||||
|
if (newAmount > prevAmount)
|
||||||
|
{
|
||||||
|
int increase = newAmount - prevAmount;
|
||||||
|
AddMessage("+" + TextManager.GetWithVariable("currencyformat", "[credits]", "[value]"),
|
||||||
|
GUI.Style.Yellow, playSound: this == Controlled, "money", increase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
partial void OnTalentGiven(string talentIdentifier)
|
||||||
|
{
|
||||||
|
AddMessage(TextManager.Get("talentname." + talentIdentifier.ToString()), GUI.Style.Yellow, playSound: this == Controlled);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool shouldRecreateHudTexts = true;
|
public static bool ShouldRecreateHudTexts { get; set; } = true;
|
||||||
private static bool heldDownShiftWhenGotHudTexts;
|
private static bool heldDownShiftWhenGotHudTexts;
|
||||||
|
|
||||||
public static bool IsCampaignInterfaceOpen =>
|
public static bool IsCampaignInterfaceOpen =>
|
||||||
@@ -150,7 +150,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (character.IsHumanoid && character.SelectedCharacter != null)
|
if (character.Params.CanInteract && character.SelectedCharacter != null)
|
||||||
{
|
{
|
||||||
character.SelectedCharacter.CharacterHealth.AddToGUIUpdateList();
|
character.SelectedCharacter.CharacterHealth.AddToGUIUpdateList();
|
||||||
}
|
}
|
||||||
@@ -195,7 +195,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (character.IsHumanoid && character.SelectedCharacter != null && character.SelectedCharacter.Inventory != null)
|
if (character.Params.CanInteract && character.SelectedCharacter != null && character.SelectedCharacter.Inventory != null)
|
||||||
{
|
{
|
||||||
if (character.SelectedCharacter.CanInventoryBeAccessed)
|
if (character.SelectedCharacter.CanInventoryBeAccessed)
|
||||||
{
|
{
|
||||||
@@ -219,7 +219,7 @@ namespace Barotrauma
|
|||||||
if (focusedItemOverlayTimer <= 0.0f)
|
if (focusedItemOverlayTimer <= 0.0f)
|
||||||
{
|
{
|
||||||
focusedItem = null;
|
focusedItem = null;
|
||||||
shouldRecreateHudTexts = true;
|
ShouldRecreateHudTexts = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -285,6 +285,21 @@ namespace Barotrauma
|
|||||||
i.GetRootInventoryOwner() == i);
|
i.GetRootInventoryOwner() == i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GameMain.GameSession != null)
|
||||||
|
{
|
||||||
|
foreach (var mission in GameMain.GameSession.Missions)
|
||||||
|
{
|
||||||
|
if (!mission.DisplayTargetHudIcons) { continue; }
|
||||||
|
foreach (var target in mission.HudIconTargets)
|
||||||
|
{
|
||||||
|
if (target.Submarine != character.Submarine) { continue; }
|
||||||
|
float alpha = GetDistanceBasedIconAlpha(target, maxDistance: mission.Prefab.HudIconMaxDistance);
|
||||||
|
if (alpha <= 0.0f) { continue; }
|
||||||
|
GUI.DrawIndicator(spriteBatch, target.DrawPosition, cam, 100.0f, mission.Prefab.HudIcon, mission.Prefab.HudIconColor * alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (Character.ObjectiveEntity objectiveEntity in character.ActiveObjectiveEntities)
|
foreach (Character.ObjectiveEntity objectiveEntity in character.ActiveObjectiveEntities)
|
||||||
{
|
{
|
||||||
DrawObjectiveIndicator(spriteBatch, cam, character, objectiveEntity, 1.0f);
|
DrawObjectiveIndicator(spriteBatch, cam, character, objectiveEntity, 1.0f);
|
||||||
@@ -317,7 +332,7 @@ namespace Barotrauma
|
|||||||
if (focusedItem != character.FocusedItem)
|
if (focusedItem != character.FocusedItem)
|
||||||
{
|
{
|
||||||
focusedItemOverlayTimer = Math.Min(1.0f, focusedItemOverlayTimer);
|
focusedItemOverlayTimer = Math.Min(1.0f, focusedItemOverlayTimer);
|
||||||
shouldRecreateHudTexts = true;
|
ShouldRecreateHudTexts = true;
|
||||||
}
|
}
|
||||||
focusedItem = character.FocusedItem;
|
focusedItem = character.FocusedItem;
|
||||||
}
|
}
|
||||||
@@ -342,13 +357,13 @@ namespace Barotrauma
|
|||||||
if (!GUI.DisableItemHighlights && !Inventory.DraggingItemToWorld)
|
if (!GUI.DisableItemHighlights && !Inventory.DraggingItemToWorld)
|
||||||
{
|
{
|
||||||
bool shiftDown = PlayerInput.IsShiftDown();
|
bool shiftDown = PlayerInput.IsShiftDown();
|
||||||
if (shouldRecreateHudTexts || heldDownShiftWhenGotHudTexts != shiftDown)
|
if (ShouldRecreateHudTexts || heldDownShiftWhenGotHudTexts != shiftDown)
|
||||||
{
|
{
|
||||||
shouldRecreateHudTexts = true;
|
ShouldRecreateHudTexts = true;
|
||||||
heldDownShiftWhenGotHudTexts = shiftDown;
|
heldDownShiftWhenGotHudTexts = shiftDown;
|
||||||
}
|
}
|
||||||
var hudTexts = focusedItem.GetHUDTexts(character, shouldRecreateHudTexts);
|
var hudTexts = focusedItem.GetHUDTexts(character, ShouldRecreateHudTexts);
|
||||||
shouldRecreateHudTexts = false;
|
ShouldRecreateHudTexts = false;
|
||||||
|
|
||||||
int dir = Math.Sign(focusedItem.WorldPosition.X - character.WorldPosition.X);
|
int dir = Math.Sign(focusedItem.WorldPosition.X - character.WorldPosition.X);
|
||||||
|
|
||||||
@@ -391,7 +406,26 @@ namespace Barotrauma
|
|||||||
if (npc.CampaignInteractionType == CampaignMode.InteractionType.None || npc.Submarine != character.Submarine || npc.IsDead || npc.IsIncapacitated) { continue; }
|
if (npc.CampaignInteractionType == CampaignMode.InteractionType.None || npc.Submarine != character.Submarine || npc.IsDead || npc.IsIncapacitated) { continue; }
|
||||||
|
|
||||||
var iconStyle = GUI.Style.GetComponentStyle("CampaignInteractionIcon." + npc.CampaignInteractionType);
|
var iconStyle = GUI.Style.GetComponentStyle("CampaignInteractionIcon." + npc.CampaignInteractionType);
|
||||||
GUI.DrawIndicator(spriteBatch, npc.WorldPosition, cam, npc.CurrentHull == character.CurrentHull ? 500.0f : 100.0f, iconStyle.GetDefaultSprite(), iconStyle.Color);
|
Range<float> visibleRange = new Range<float>(npc.CurrentHull == Character.Controlled.CurrentHull ? 500.0f : 100.0f, float.PositiveInfinity);
|
||||||
|
if (npc.CampaignInteractionType == CampaignMode.InteractionType.Examine)
|
||||||
|
{
|
||||||
|
//TODO: we could probably do better than just hardcoding
|
||||||
|
//a check for InteractionType.Examine here.
|
||||||
|
|
||||||
|
if (Vector2.DistanceSquared(character.Position, npc.Position) > 500f * 500f) { continue; }
|
||||||
|
|
||||||
|
var body = Submarine.CheckVisibility(character.SimPosition, npc.SimPosition, ignoreLevel: true);
|
||||||
|
if (body != null && body.UserData as Character != npc) { continue; }
|
||||||
|
|
||||||
|
visibleRange = new Range<float>(-100f, 500f);
|
||||||
|
}
|
||||||
|
GUI.DrawIndicator(
|
||||||
|
spriteBatch,
|
||||||
|
npc.WorldPosition,
|
||||||
|
cam,
|
||||||
|
visibleRange,
|
||||||
|
iconStyle.GetDefaultSprite(),
|
||||||
|
iconStyle.Color);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Item item in Item.ItemList)
|
foreach (Item item in Item.ItemList)
|
||||||
@@ -400,7 +434,7 @@ namespace Barotrauma
|
|||||||
if (Vector2.DistanceSquared(character.Position, item.Position) > 500f*500f) { continue; }
|
if (Vector2.DistanceSquared(character.Position, item.Position) > 500f*500f) { continue; }
|
||||||
var body = Submarine.CheckVisibility(character.SimPosition, item.SimPosition, ignoreLevel: true);
|
var body = Submarine.CheckVisibility(character.SimPosition, item.SimPosition, ignoreLevel: true);
|
||||||
if (body != null && body.UserData as Item != item) { continue; }
|
if (body != null && body.UserData as Item != item) { continue; }
|
||||||
GUI.DrawIndicator(spriteBatch, item.WorldPosition + new Vector2(0f, item.RectHeight * 0.65f), cam, new Vector2(-100f, 500.0f), item.IconStyle.GetDefaultSprite(), item.IconStyle.Color, createOffset: false);
|
GUI.DrawIndicator(spriteBatch, item.WorldPosition + new Vector2(0f, item.RectHeight * 0.65f), cam, new Range<float>(-100f, 500.0f), item.IconStyle.GetDefaultSprite(), item.IconStyle.Color, createOffset: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -471,7 +505,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (!character.IsIncapacitated && character.Stun <= 0.0f)
|
if (!character.IsIncapacitated && character.Stun <= 0.0f)
|
||||||
{
|
{
|
||||||
if (character.IsHumanoid && character.SelectedCharacter != null && character.SelectedCharacter.Inventory != null)
|
if (character.Params.CanInteract && character.SelectedCharacter != null && character.SelectedCharacter.Inventory != null)
|
||||||
{
|
{
|
||||||
if (character.SelectedCharacter.CanInventoryBeAccessed)
|
if (character.SelectedCharacter.CanInventoryBeAccessed)
|
||||||
{
|
{
|
||||||
@@ -525,12 +559,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
textPos -= new Vector2(textSize.X / 2, textSize.Y);
|
textPos -= new Vector2(textSize.X / 2, textSize.Y);
|
||||||
|
|
||||||
Color nameColor = GUI.Style.TextColor;
|
Color nameColor = character.FocusedCharacter.GetNameColor();
|
||||||
if (character.TeamID != character.FocusedCharacter.TeamID)
|
|
||||||
{
|
|
||||||
nameColor = character.FocusedCharacter.TeamID == CharacterTeamType.FriendlyNPC ? Color.SkyBlue : GUI.Style.Red;
|
|
||||||
}
|
|
||||||
|
|
||||||
GUI.DrawString(spriteBatch, textPos, focusName, nameColor, Color.Black * 0.7f, 2, GUI.SubHeadingFont);
|
GUI.DrawString(spriteBatch, textPos, focusName, nameColor, Color.Black * 0.7f, 2, GUI.SubHeadingFont);
|
||||||
textPos.X += 10.0f * GUI.Scale;
|
textPos.X += 10.0f * GUI.Scale;
|
||||||
textPos.Y += GUI.SubHeadingFont.MeasureString(focusName).Y;
|
textPos.Y += GUI.SubHeadingFont.MeasureString(focusName).Y;
|
||||||
@@ -544,11 +573,14 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (character.FocusedCharacter.CanBeDragged)
|
if (character.FocusedCharacter.CanBeDragged)
|
||||||
{
|
{
|
||||||
GUI.DrawString(spriteBatch, textPos, GetCachedHudText("GrabHint", GameMain.Config.KeyBindText(InputType.Grab)),
|
string text = character.CanEat ? "EatHint" : "GrabHint";
|
||||||
|
GUI.DrawString(spriteBatch, textPos, GetCachedHudText(text, GameMain.Config.KeyBindText(InputType.Grab)),
|
||||||
GUI.Style.Green, Color.Black, 2, GUI.SmallFont);
|
GUI.Style.Green, Color.Black, 2, GUI.SmallFont);
|
||||||
textPos.Y += largeTextSize.Y;
|
textPos.Y += largeTextSize.Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!character.DisableHealthWindow &&
|
if (!character.DisableHealthWindow &&
|
||||||
|
character.IsFriendly(character.FocusedCharacter) &&
|
||||||
character.FocusedCharacter.CharacterHealth.UseHealthWindow &&
|
character.FocusedCharacter.CharacterHealth.UseHealthWindow &&
|
||||||
character.CanInteractWith(character.FocusedCharacter, 160f, false))
|
character.CanInteractWith(character.FocusedCharacter, 160f, false))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,11 +17,19 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public bool LastControlled;
|
public bool LastControlled;
|
||||||
|
|
||||||
|
#warning TODO: Refactor
|
||||||
private Sprite disguisedPortrait;
|
private Sprite disguisedPortrait;
|
||||||
private List<WearableSprite> disguisedAttachmentSprites;
|
private List<WearableSprite> disguisedAttachmentSprites;
|
||||||
private Vector2? disguisedSheetIndex;
|
private Vector2? disguisedSheetIndex;
|
||||||
private Sprite disguisedJobIcon;
|
private Sprite disguisedJobIcon;
|
||||||
private Color disguisedJobColor;
|
private Color disguisedJobColor;
|
||||||
|
private Color disguisedHairColor;
|
||||||
|
private Color disguisedFacialHairColor;
|
||||||
|
private Color disguisedSkinColor;
|
||||||
|
|
||||||
|
private Sprite tintMask;
|
||||||
|
private float tintHighlightThreshold;
|
||||||
|
private float tintHighlightMultiplier;
|
||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
{
|
||||||
@@ -29,6 +37,20 @@ namespace Barotrauma
|
|||||||
new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(833, 298, 142, 98), null, 0);
|
new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(833, 298, 142, 98), null, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
partial void LoadHeadSpriteProjectSpecific(XElement limbElement)
|
||||||
|
{
|
||||||
|
XElement maskElement = limbElement.Element("tintmask");
|
||||||
|
if (maskElement != null)
|
||||||
|
{
|
||||||
|
string tintMaskPath = maskElement.GetAttributeString("texture", "");
|
||||||
|
if (!string.IsNullOrWhiteSpace(tintMaskPath))
|
||||||
|
{
|
||||||
|
tintMask = new Sprite(maskElement, file: Limb.GetSpritePath(tintMaskPath, this));
|
||||||
|
tintHighlightThreshold = maskElement.GetAttributeFloat("highlightthreshold", 0.6f);
|
||||||
|
tintHighlightMultiplier = maskElement.GetAttributeFloat("highlightmultiplier", 0.8f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public GUIComponent CreateInfoFrame(GUIFrame frame, bool returnParent, Sprite permissionIcon = null)
|
public GUIComponent CreateInfoFrame(GUIFrame frame, bool returnParent, Sprite permissionIcon = null)
|
||||||
{
|
{
|
||||||
@@ -143,10 +165,10 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private void DrawInfoFrameCharacterIcon(SpriteBatch sb, Rectangle componentRect)
|
private void DrawInfoFrameCharacterIcon(SpriteBatch sb, Rectangle componentRect)
|
||||||
{
|
{
|
||||||
if (headSprite == null) { return; }
|
if (_headSprite == null) { return; }
|
||||||
Vector2 targetAreaSize = componentRect.Size.ToVector2();
|
Vector2 targetAreaSize = componentRect.Size.ToVector2();
|
||||||
float scale = Math.Min(targetAreaSize.X / headSprite.size.X, targetAreaSize.Y / headSprite.size.Y);
|
float scale = Math.Min(targetAreaSize.X / _headSprite.size.X, targetAreaSize.Y / _headSprite.size.Y);
|
||||||
DrawIcon(sb, componentRect.Location.ToVector2() + headSprite.size / 2 * scale, targetAreaSize);
|
DrawIcon(sb, componentRect.Location.ToVector2() + _headSprite.size / 2 * scale, targetAreaSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GUIFrame CreateCharacterFrame(GUIComponent parent, string text, object userData)
|
public GUIFrame CreateCharacterFrame(GUIComponent parent, string text, object userData)
|
||||||
@@ -165,21 +187,36 @@ namespace Barotrauma
|
|||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void OnSkillChanged(string skillIdentifier, float prevLevel, float newLevel, Vector2 textPopupPos)
|
partial void OnSkillChanged(string skillIdentifier, float prevLevel, float newLevel)
|
||||||
{
|
{
|
||||||
if (TeamID == CharacterTeamType.FriendlyNPC) { return; }
|
if (TeamID == CharacterTeamType.FriendlyNPC) { return; }
|
||||||
if (Character.Controlled != null && Character.Controlled.TeamID != TeamID) { return; }
|
if (Character.Controlled != null && Character.Controlled.TeamID != TeamID) { return; }
|
||||||
|
|
||||||
|
// if we increased by more than 1 in one increase, then display special color (for talents)
|
||||||
|
bool specialIncrease = Math.Abs(newLevel - prevLevel) >= 1.0f;
|
||||||
|
|
||||||
if ((int)newLevel > (int)prevLevel)
|
if ((int)newLevel > (int)prevLevel)
|
||||||
{
|
{
|
||||||
int increase = Math.Max((int)newLevel - (int)prevLevel, 1);
|
int increase = Math.Max((int)newLevel - (int)prevLevel, 1);
|
||||||
GUI.AddMessage(
|
Character?.AddMessage(
|
||||||
string.Format("+{0} {1}", increase, TextManager.Get("SkillName." + skillIdentifier)),
|
"+[value] "+ TextManager.Get("SkillName." + skillIdentifier),
|
||||||
GUI.Style.Green,
|
specialIncrease ? GUI.Style.Orange : GUI.Style.Green,
|
||||||
textPopupPos,
|
playSound: Character == Character.Controlled, skillIdentifier, increase);
|
||||||
Vector2.UnitY * 10.0f,
|
}
|
||||||
playSound: false,
|
}
|
||||||
subId: Character?.Submarine?.ID ?? -1);
|
|
||||||
|
partial void OnExperienceChanged(int prevAmount, int newAmount)
|
||||||
|
{
|
||||||
|
if (Character.Controlled != null && Character.Controlled.TeamID != TeamID) { return; }
|
||||||
|
|
||||||
|
GameSession.TabMenuInstance?.OnExperienceChanged(Character);
|
||||||
|
|
||||||
|
if (newAmount > prevAmount)
|
||||||
|
{
|
||||||
|
int increase = newAmount - prevAmount;
|
||||||
|
Character?.AddMessage(
|
||||||
|
"+[value] " + TextManager.Get("experienceshort"),
|
||||||
|
GUI.Style.Blue, playSound: Character == Character.Controlled, "exp", increase);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,193 +224,36 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (idCard.Item.Tags == string.Empty) return;
|
if (idCard.Item.Tags == string.Empty) return;
|
||||||
|
|
||||||
if (idCard.StoredJobPrefab == null || idCard.StoredPortrait == null)
|
if (idCard.StoredOwnerAppearance.JobPrefab == null || idCard.StoredOwnerAppearance.Portrait == null)
|
||||||
{
|
{
|
||||||
string[] readTags = idCard.Item.Tags.Split(',');
|
string[] readTags = idCard.Item.Tags.Split(',');
|
||||||
|
|
||||||
if (readTags.Length == 0) return;
|
if (readTags.Length == 0) { return; }
|
||||||
|
|
||||||
if (idCard.StoredJobPrefab == null)
|
if (idCard.StoredOwnerAppearance.JobPrefab == null)
|
||||||
{
|
{
|
||||||
string jobIdTag = readTags.FirstOrDefault(s => s.StartsWith("jobid:"));
|
idCard.StoredOwnerAppearance.ExtractJobPrefab(readTags);
|
||||||
|
|
||||||
if (jobIdTag != null && jobIdTag.Length > 6)
|
|
||||||
{
|
|
||||||
string jobId = jobIdTag.Substring(6);
|
|
||||||
if (jobId != string.Empty)
|
|
||||||
{
|
|
||||||
idCard.StoredJobPrefab = JobPrefab.Get(jobId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idCard.StoredPortrait == null)
|
if (idCard.StoredOwnerAppearance.Portrait == null)
|
||||||
{
|
{
|
||||||
string disguisedGender = string.Empty;
|
idCard.StoredOwnerAppearance.ExtractAppearance(this, readTags);
|
||||||
string disguisedRace = string.Empty;
|
|
||||||
string disguisedHeadSpriteId = string.Empty;
|
|
||||||
int disguisedHairIndex = -1;
|
|
||||||
int disguisedBeardIndex = -1;
|
|
||||||
int disguisedMoustacheIndex = -1;
|
|
||||||
int disguisedFaceAttachmentIndex = -1;
|
|
||||||
|
|
||||||
foreach (string tag in readTags)
|
|
||||||
{
|
|
||||||
string[] s = tag.Split(':');
|
|
||||||
|
|
||||||
switch (s[0])
|
|
||||||
{
|
|
||||||
case "gender":
|
|
||||||
disguisedGender = s[1];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "race":
|
|
||||||
disguisedRace = s[1];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "headspriteid":
|
|
||||||
disguisedHeadSpriteId = s[1];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "hairindex":
|
|
||||||
disguisedHairIndex = int.Parse(s[1]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "beardindex":
|
|
||||||
disguisedBeardIndex = int.Parse(s[1]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "moustacheindex":
|
|
||||||
disguisedMoustacheIndex = int.Parse(s[1]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "faceattachmentindex":
|
|
||||||
disguisedFaceAttachmentIndex = int.Parse(s[1]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "sheetindex":
|
|
||||||
string[] vectorValues = s[1].Split(";");
|
|
||||||
idCard.StoredSheetIndex = new Vector2(float.Parse(vectorValues[0]), float.Parse(vectorValues[1]));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (disguisedGender == string.Empty || disguisedRace == string.Empty || disguisedHeadSpriteId == string.Empty)
|
|
||||||
{
|
|
||||||
idCard.StoredPortrait = null;
|
|
||||||
idCard.StoredAttachments = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (XElement limbElement in Ragdoll.MainElement.Elements())
|
|
||||||
{
|
|
||||||
if (!limbElement.GetAttributeString("type", "").Equals("head", StringComparison.OrdinalIgnoreCase)) { continue; }
|
|
||||||
|
|
||||||
XElement spriteElement = limbElement.Element("sprite");
|
|
||||||
if (spriteElement == null) { continue; }
|
|
||||||
|
|
||||||
string spritePath = spriteElement.Attribute("texture").Value;
|
|
||||||
|
|
||||||
spritePath = spritePath.Replace("[GENDER]", disguisedGender);
|
|
||||||
spritePath = spritePath.Replace("[RACE]", disguisedRace.ToLowerInvariant());
|
|
||||||
spritePath = spritePath.Replace("[HEADID]", disguisedHeadSpriteId);
|
|
||||||
|
|
||||||
string fileName = Path.GetFileNameWithoutExtension(spritePath);
|
|
||||||
|
|
||||||
//go through the files in the directory to find a matching sprite
|
|
||||||
foreach (string file in Directory.GetFiles(Path.GetDirectoryName(spritePath)))
|
|
||||||
{
|
|
||||||
if (!file.EndsWith(".png", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
string fileWithoutTags = Path.GetFileNameWithoutExtension(file);
|
|
||||||
fileWithoutTags = fileWithoutTags.Split('[', ']').First();
|
|
||||||
if (fileWithoutTags != fileName) { continue; }
|
|
||||||
idCard.StoredPortrait = new Sprite(spriteElement, "", file) { RelativeOrigin = Vector2.Zero };
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Wearables != null)
|
|
||||||
{
|
|
||||||
XElement disguisedHairElement, disguisedBeardElement, disguisedMoustacheElement, disguisedFaceAttachmentElement;
|
|
||||||
List<XElement> disguisedHairs, disguisedBeards, disguisedMoustaches, disguisedFaceAttachments;
|
|
||||||
|
|
||||||
Gender disguisedGenderEnum = disguisedGender == "female" ? Gender.Female : Gender.Male;
|
|
||||||
Race disguisedRaceEnum = (Race)Enum.Parse(typeof(Race), disguisedRace);
|
|
||||||
int headSpriteId = int.Parse(disguisedHeadSpriteId);
|
|
||||||
|
|
||||||
float commonness = disguisedGenderEnum == Gender.Female ? 0.05f : 0.2f;
|
|
||||||
disguisedHairs = AddEmpty(FilterByTypeAndHeadID(FilterElementsByGenderAndRace(wearables, disguisedGenderEnum, disguisedRaceEnum), WearableType.Hair, headSpriteId), WearableType.Hair, commonness);
|
|
||||||
disguisedBeards = AddEmpty(FilterByTypeAndHeadID(FilterElementsByGenderAndRace(wearables, disguisedGenderEnum, disguisedRaceEnum), WearableType.Beard, headSpriteId), WearableType.Beard);
|
|
||||||
disguisedMoustaches = AddEmpty(FilterByTypeAndHeadID(FilterElementsByGenderAndRace(wearables, disguisedGenderEnum, disguisedRaceEnum), WearableType.Moustache, headSpriteId), WearableType.Moustache);
|
|
||||||
disguisedFaceAttachments = AddEmpty(FilterByTypeAndHeadID(FilterElementsByGenderAndRace(wearables, disguisedGenderEnum, disguisedRaceEnum), WearableType.FaceAttachment, headSpriteId), WearableType.FaceAttachment);
|
|
||||||
|
|
||||||
if (IsValidIndex(disguisedHairIndex, disguisedHairs))
|
|
||||||
{
|
|
||||||
disguisedHairElement = disguisedHairs[disguisedHairIndex];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
disguisedHairElement = GetRandomElement(disguisedHairs);
|
|
||||||
}
|
|
||||||
if (IsValidIndex(disguisedBeardIndex, disguisedBeards))
|
|
||||||
{
|
|
||||||
disguisedBeardElement = disguisedBeards[disguisedBeardIndex];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
disguisedBeardElement = GetRandomElement(disguisedBeards);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsValidIndex(disguisedMoustacheIndex, disguisedMoustaches))
|
|
||||||
{
|
|
||||||
disguisedMoustacheElement = disguisedMoustaches[disguisedMoustacheIndex];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
disguisedMoustacheElement = GetRandomElement(disguisedMoustaches);
|
|
||||||
}
|
|
||||||
if (IsValidIndex(disguisedFaceAttachmentIndex, disguisedFaceAttachments))
|
|
||||||
{
|
|
||||||
disguisedFaceAttachmentElement = disguisedFaceAttachments[disguisedFaceAttachmentIndex];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
disguisedFaceAttachmentElement = GetRandomElement(disguisedFaceAttachments);
|
|
||||||
}
|
|
||||||
|
|
||||||
idCard.StoredAttachments = new List<WearableSprite>();
|
|
||||||
|
|
||||||
disguisedFaceAttachmentElement?.Elements("sprite").ForEach(s => idCard.StoredAttachments.Add(new WearableSprite(s, WearableType.FaceAttachment)));
|
|
||||||
disguisedBeardElement?.Elements("sprite").ForEach(s => idCard.StoredAttachments.Add(new WearableSprite(s, WearableType.Beard)));
|
|
||||||
disguisedMoustacheElement?.Elements("sprite").ForEach(s => idCard.StoredAttachments.Add(new WearableSprite(s, WearableType.Moustache)));
|
|
||||||
disguisedHairElement?.Elements("sprite").ForEach(s => idCard.StoredAttachments.Add(new WearableSprite(s, WearableType.Hair)));
|
|
||||||
|
|
||||||
if (OmitJobInPortraitClothing)
|
|
||||||
{
|
|
||||||
JobPrefab.NoJobElement?.Element("PortraitClothing")?.Elements("sprite").ForEach(s => idCard.StoredAttachments.Add(new WearableSprite(s, WearableType.JobIndicator)));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
idCard.StoredJobPrefab?.ClothingElement?.Elements("sprite").ForEach(s => idCard.StoredAttachments.Add(new WearableSprite(s, WearableType.JobIndicator)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idCard.StoredJobPrefab != null)
|
if (idCard.StoredOwnerAppearance.JobPrefab != null)
|
||||||
{
|
{
|
||||||
disguisedJobIcon = idCard.StoredJobPrefab.Icon;
|
disguisedJobIcon = idCard.StoredOwnerAppearance.JobPrefab.Icon;
|
||||||
disguisedJobColor = idCard.StoredJobPrefab.UIColor;
|
disguisedJobColor = idCard.StoredOwnerAppearance.JobPrefab.UIColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
disguisedPortrait = idCard.StoredPortrait;
|
disguisedPortrait = idCard.StoredOwnerAppearance.Portrait;
|
||||||
disguisedSheetIndex = idCard.StoredSheetIndex;
|
disguisedSheetIndex = idCard.StoredOwnerAppearance.SheetIndex;
|
||||||
disguisedAttachmentSprites = idCard.StoredAttachments;
|
disguisedAttachmentSprites = idCard.StoredOwnerAppearance.Attachments;
|
||||||
|
|
||||||
|
disguisedHairColor = idCard.StoredOwnerAppearance.HairColor;
|
||||||
|
disguisedFacialHairColor = idCard.StoredOwnerAppearance.FacialHairColor;
|
||||||
|
disguisedSkinColor = idCard.StoredOwnerAppearance.SkinColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void LoadAttachmentSprites(bool omitJob)
|
partial void LoadAttachmentSprites(bool omitJob)
|
||||||
@@ -422,43 +302,107 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void DrawPortrait(SpriteBatch spriteBatch, Vector2 screenPos, Vector2 offset, float targetWidth, bool flip = false, bool evaluateDisguise = false)
|
public void DrawPortrait(SpriteBatch spriteBatch, Vector2 screenPos, Vector2 offset, float targetWidth, bool flip = false, bool evaluateDisguise = false)
|
||||||
{
|
{
|
||||||
if (evaluateDisguise && IsDisguised) return;
|
if (evaluateDisguise && IsDisguised) { return; }
|
||||||
|
|
||||||
Vector2? sheetIndex;
|
Vector2? sheetIndex;
|
||||||
Sprite portraitToDraw;
|
Sprite portraitToDraw;
|
||||||
List<WearableSprite> attachmentsToDraw;
|
List<WearableSprite> attachmentsToDraw;
|
||||||
|
|
||||||
|
Color hairColor;
|
||||||
|
Color facialHairColor;
|
||||||
|
Color skinColor;
|
||||||
|
|
||||||
if (!IsDisguisedAsAnother || !evaluateDisguise)
|
if (!IsDisguisedAsAnother || !evaluateDisguise)
|
||||||
{
|
{
|
||||||
sheetIndex = Head.SheetIndex;
|
sheetIndex = Head.SheetIndex;
|
||||||
portraitToDraw = Portrait;
|
portraitToDraw = Portrait;
|
||||||
attachmentsToDraw = AttachmentSprites;
|
attachmentsToDraw = AttachmentSprites;
|
||||||
|
|
||||||
|
hairColor = Head.HairColor;
|
||||||
|
facialHairColor = Head.FacialHairColor;
|
||||||
|
skinColor = Head.SkinColor;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sheetIndex = disguisedSheetIndex;
|
sheetIndex = disguisedSheetIndex;
|
||||||
portraitToDraw = disguisedPortrait;
|
portraitToDraw = disguisedPortrait;
|
||||||
attachmentsToDraw = disguisedAttachmentSprites;
|
attachmentsToDraw = disguisedAttachmentSprites;
|
||||||
|
|
||||||
|
hairColor = disguisedHairColor;
|
||||||
|
facialHairColor = disguisedFacialHairColor;
|
||||||
|
skinColor = disguisedSkinColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (portraitToDraw != null)
|
if (portraitToDraw != null)
|
||||||
{
|
{
|
||||||
|
var currEffect = spriteBatch.GetCurrentEffect();
|
||||||
// Scale down the head sprite 10%
|
// Scale down the head sprite 10%
|
||||||
float scale = targetWidth * 0.9f / Portrait.size.X;
|
float scale = targetWidth * 0.9f / Portrait.size.X;
|
||||||
if (sheetIndex.HasValue)
|
if (sheetIndex.HasValue)
|
||||||
{
|
{
|
||||||
|
SetHeadEffect(spriteBatch);
|
||||||
portraitToDraw.SourceRect = new Rectangle(CalculateOffset(portraitToDraw, sheetIndex.Value.ToPoint()), portraitToDraw.SourceRect.Size);
|
portraitToDraw.SourceRect = new Rectangle(CalculateOffset(portraitToDraw, sheetIndex.Value.ToPoint()), portraitToDraw.SourceRect.Size);
|
||||||
}
|
}
|
||||||
portraitToDraw.Draw(spriteBatch, screenPos + offset, Color.White, portraitToDraw.Origin, scale: scale, spriteEffect: flip ? SpriteEffects.FlipHorizontally : SpriteEffects.None);
|
portraitToDraw.Draw(spriteBatch, screenPos + offset, skinColor, portraitToDraw.Origin, scale: scale, spriteEffect: flip ? SpriteEffects.FlipHorizontally : SpriteEffects.None);
|
||||||
if (attachmentsToDraw != null)
|
if (attachmentsToDraw != null)
|
||||||
{
|
{
|
||||||
float depthStep = 0.000001f;
|
float depthStep = 0.000001f;
|
||||||
foreach (var attachment in attachmentsToDraw)
|
foreach (var attachment in attachmentsToDraw)
|
||||||
{
|
{
|
||||||
DrawAttachmentSprite(spriteBatch, attachment, portraitToDraw, sheetIndex, screenPos + offset, scale, depthStep, flip ? SpriteEffects.FlipHorizontally : SpriteEffects.None);
|
SetAttachmentEffect(spriteBatch, attachment);
|
||||||
|
DrawAttachmentSprite(spriteBatch, attachment, portraitToDraw, sheetIndex, screenPos + offset, scale, depthStep, GetAttachmentColor(attachment, hairColor, facialHairColor), flip ? SpriteEffects.FlipHorizontally : SpriteEffects.None);
|
||||||
depthStep += depthStep;
|
depthStep += depthStep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
spriteBatch.SwapEffect(currEffect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: I hate this so much :(
|
||||||
|
private SpriteBatch.EffectWithParams headEffectParameters;
|
||||||
|
private Dictionary<WearableType, SpriteBatch.EffectWithParams> attachmentEffectParameters
|
||||||
|
= new Dictionary<WearableType, SpriteBatch.EffectWithParams>();
|
||||||
|
|
||||||
|
private void SetHeadEffect(SpriteBatch spriteBatch)
|
||||||
|
{
|
||||||
|
headEffectParameters.Effect ??= GameMain.GameScreen.ThresholdTintEffect;
|
||||||
|
headEffectParameters.Params ??= new Dictionary<string, object>();
|
||||||
|
headEffectParameters.Params["xBaseTexture"] = HeadSprite.Texture;
|
||||||
|
headEffectParameters.Params["xTintMaskTexture"] = tintMask?.Texture ?? GUI.WhiteTexture;
|
||||||
|
headEffectParameters.Params["xCutoffTexture"] = GUI.WhiteTexture;
|
||||||
|
headEffectParameters.Params["baseToCutoffSizeRatio"] = 1.0f;
|
||||||
|
headEffectParameters.Params["highlightThreshold"] = tintHighlightThreshold;
|
||||||
|
headEffectParameters.Params["highlightMultiplier"] = tintHighlightMultiplier;
|
||||||
|
spriteBatch.SwapEffect(headEffectParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetAttachmentEffect(SpriteBatch spriteBatch, WearableSprite attachment)
|
||||||
|
{
|
||||||
|
if (!attachmentEffectParameters.ContainsKey(attachment.Type))
|
||||||
|
{
|
||||||
|
attachmentEffectParameters.Add(attachment.Type, new SpriteBatch.EffectWithParams(GameMain.GameScreen.ThresholdTintEffect, new Dictionary<string, object>()));
|
||||||
|
}
|
||||||
|
var parameters = attachmentEffectParameters[attachment.Type].Params;
|
||||||
|
parameters["xBaseTexture"] = attachment.Sprite.Texture;
|
||||||
|
parameters["xTintMaskTexture"] = GUI.WhiteTexture;
|
||||||
|
parameters["xCutoffTexture"] = GUI.WhiteTexture;
|
||||||
|
parameters["baseToCutoffSizeRatio"] = 1.0f;
|
||||||
|
parameters["highlightThreshold"] = tintHighlightThreshold;
|
||||||
|
parameters["highlightMultiplier"] = tintHighlightMultiplier;
|
||||||
|
spriteBatch.SwapEffect(attachmentEffectParameters[attachment.Type]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color GetAttachmentColor(WearableSprite attachment, Color hairColor, Color facialHairColor)
|
||||||
|
{
|
||||||
|
switch (attachment.Type)
|
||||||
|
{
|
||||||
|
case WearableType.Hair:
|
||||||
|
return hairColor;
|
||||||
|
case WearableType.Beard:
|
||||||
|
case WearableType.Moustache:
|
||||||
|
return facialHairColor;
|
||||||
|
default:
|
||||||
|
return Color.White;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -467,34 +411,28 @@ namespace Barotrauma
|
|||||||
var headSprite = HeadSprite;
|
var headSprite = HeadSprite;
|
||||||
if (headSprite != null)
|
if (headSprite != null)
|
||||||
{
|
{
|
||||||
|
var currEffect = spriteBatch.GetCurrentEffect();
|
||||||
float scale = Math.Min(targetAreaSize.X / headSprite.size.X, targetAreaSize.Y / headSprite.size.Y);
|
float scale = Math.Min(targetAreaSize.X / headSprite.size.X, targetAreaSize.Y / headSprite.size.Y);
|
||||||
if (Head.SheetIndex.HasValue)
|
if (Head.SheetIndex.HasValue)
|
||||||
{
|
{
|
||||||
headSprite.SourceRect = new Rectangle(CalculateOffset(headSprite, Head.SheetIndex.Value.ToPoint()), headSprite.SourceRect.Size);
|
headSprite.SourceRect = new Rectangle(CalculateOffset(headSprite, Head.SheetIndex.Value.ToPoint()), headSprite.SourceRect.Size);
|
||||||
}
|
}
|
||||||
headSprite.Draw(spriteBatch, screenPos, scale: scale);
|
SetHeadEffect(spriteBatch);
|
||||||
|
headSprite.Draw(spriteBatch, screenPos, scale: scale, color: SkinColor);
|
||||||
if (AttachmentSprites != null)
|
if (AttachmentSprites != null)
|
||||||
{
|
{
|
||||||
float depthStep = 0.000001f;
|
float depthStep = 0.000001f;
|
||||||
foreach (var attachment in AttachmentSprites)
|
foreach (var attachment in AttachmentSprites)
|
||||||
{
|
{
|
||||||
DrawAttachmentSprite(spriteBatch, attachment, headSprite, Head.SheetIndex, screenPos, scale, depthStep);
|
SetAttachmentEffect(spriteBatch, attachment);
|
||||||
|
DrawAttachmentSprite(spriteBatch, attachment, headSprite, Head.SheetIndex, screenPos, scale, depthStep, GetAttachmentColor(attachment, HairColor, FacialHairColor));
|
||||||
depthStep += depthStep;
|
depthStep += depthStep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
spriteBatch.SwapEffect(currEffect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DrawJobIcon(SpriteBatch spriteBatch, Vector2 pos, float scale = 1.0f, bool evaluateDisguise = false)
|
|
||||||
{
|
|
||||||
if (evaluateDisguise && IsDisguised) return;
|
|
||||||
var icon = !IsDisguisedAsAnother || !evaluateDisguise ? Job?.Prefab?.Icon : disguisedJobIcon;
|
|
||||||
if (icon == null) { return; }
|
|
||||||
Color iconColor = !IsDisguisedAsAnother || !evaluateDisguise ? Job.Prefab.UIColor : disguisedJobColor;
|
|
||||||
|
|
||||||
icon.Draw(spriteBatch, pos, iconColor, scale: scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DrawJobIcon(SpriteBatch spriteBatch, Rectangle area, bool evaluateDisguise = false)
|
public void DrawJobIcon(SpriteBatch spriteBatch, Rectangle area, bool evaluateDisguise = false)
|
||||||
{
|
{
|
||||||
if (evaluateDisguise && IsDisguised) return;
|
if (evaluateDisguise && IsDisguised) return;
|
||||||
@@ -505,7 +443,7 @@ namespace Barotrauma
|
|||||||
icon.Draw(spriteBatch, area.Center.ToVector2(), iconColor, scale: Math.Min(area.Width / (float)icon.SourceRect.Width, area.Height / (float)icon.SourceRect.Height));
|
icon.Draw(spriteBatch, area.Center.ToVector2(), iconColor, scale: Math.Min(area.Width / (float)icon.SourceRect.Width, area.Height / (float)icon.SourceRect.Height));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawAttachmentSprite(SpriteBatch spriteBatch, WearableSprite attachment, Sprite head, Vector2? sheetIndex, Vector2 drawPos, float scale, float depthStep, SpriteEffects spriteEffects = SpriteEffects.None)
|
private void DrawAttachmentSprite(SpriteBatch spriteBatch, WearableSprite attachment, Sprite head, Vector2? sheetIndex, Vector2 drawPos, float scale, float depthStep, Color? color = null, SpriteEffects spriteEffects = SpriteEffects.None)
|
||||||
{
|
{
|
||||||
if (attachment.InheritSourceRect)
|
if (attachment.InheritSourceRect)
|
||||||
{
|
{
|
||||||
@@ -522,7 +460,7 @@ namespace Barotrauma
|
|||||||
attachment.Sprite.SourceRect = head.SourceRect;
|
attachment.Sprite.SourceRect = head.SourceRect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Vector2 origin = attachment.Sprite.Origin;
|
Vector2 origin;
|
||||||
if (attachment.InheritOrigin)
|
if (attachment.InheritOrigin)
|
||||||
{
|
{
|
||||||
origin = head.Origin;
|
origin = head.Origin;
|
||||||
@@ -537,7 +475,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
depth = head.Depth - depthStep;
|
depth = head.Depth - depthStep;
|
||||||
}
|
}
|
||||||
attachment.Sprite.Draw(spriteBatch, drawPos, Color.White, origin, rotate: 0, scale: scale, depth: depth, spriteEffect: spriteEffects);
|
attachment.Sprite.Draw(spriteBatch, drawPos, color ?? Color.White, origin, rotate: 0, scale: scale, depth: depth, spriteEffect: spriteEffects);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CharacterInfo ClientRead(string speciesName, IReadMessage inc)
|
public static CharacterInfo ClientRead(string speciesName, IReadMessage inc)
|
||||||
@@ -552,6 +490,9 @@ namespace Barotrauma
|
|||||||
int beardIndex = inc.ReadByte();
|
int beardIndex = inc.ReadByte();
|
||||||
int moustacheIndex = inc.ReadByte();
|
int moustacheIndex = inc.ReadByte();
|
||||||
int faceAttachmentIndex = inc.ReadByte();
|
int faceAttachmentIndex = inc.ReadByte();
|
||||||
|
Color skinColor = inc.ReadColorR8G8B8();
|
||||||
|
Color hairColor = inc.ReadColorR8G8B8();
|
||||||
|
Color facialHairColor = inc.ReadColorR8G8B8();
|
||||||
string ragdollFile = inc.ReadString();
|
string ragdollFile = inc.ReadString();
|
||||||
|
|
||||||
string jobIdentifier = inc.ReadString();
|
string jobIdentifier = inc.ReadString();
|
||||||
@@ -577,6 +518,9 @@ namespace Barotrauma
|
|||||||
ID = infoID,
|
ID = infoID,
|
||||||
};
|
};
|
||||||
ch.RecreateHead(headSpriteID,(Race)race, (Gender)gender, hairIndex, beardIndex, moustacheIndex, faceAttachmentIndex);
|
ch.RecreateHead(headSpriteID,(Race)race, (Gender)gender, hairIndex, beardIndex, moustacheIndex, faceAttachmentIndex);
|
||||||
|
ch.SkinColor = skinColor;
|
||||||
|
ch.HairColor = hairColor;
|
||||||
|
ch.FacialHairColor = facialHairColor;
|
||||||
if (ch.Job != null)
|
if (ch.Job != null)
|
||||||
{
|
{
|
||||||
foreach (KeyValuePair<string, float> skill in skillLevels)
|
foreach (KeyValuePair<string, float> skill in skillLevels)
|
||||||
@@ -591,7 +535,449 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
ch.Job.Skills.RemoveAll(s => !skillLevels.ContainsKey(s.Identifier));
|
ch.Job.Skills.RemoveAll(s => !skillLevels.ContainsKey(s.Identifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte savedStatValueCount = inc.ReadByte();
|
||||||
|
for (int i = 0; i < savedStatValueCount; i++)
|
||||||
|
{
|
||||||
|
int statType = inc.ReadByte();
|
||||||
|
string statIdentifier = inc.ReadString();
|
||||||
|
float statValue = inc.ReadSingle();
|
||||||
|
bool removeOnDeath = inc.ReadBoolean();
|
||||||
|
ch.ChangeSavedStatValue((StatTypes)statType, statValue, statIdentifier, removeOnDeath);
|
||||||
|
}
|
||||||
|
ch.ExperiencePoints = inc.ReadUInt16();
|
||||||
|
ch.AdditionalTalentPoints = inc.ReadUInt16();
|
||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CreateIcon(RectTransform rectT)
|
||||||
|
{
|
||||||
|
LoadHeadAttachments();
|
||||||
|
new GUICustomComponent(rectT,
|
||||||
|
onDraw: (sb, component) => DrawIcon(sb, component.Rect.Center.ToVector2(), targetAreaSize: component.Rect.Size.ToVector2()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AppearanceCustomizationMenu : IDisposable
|
||||||
|
{
|
||||||
|
public readonly CharacterInfo CharacterInfo;
|
||||||
|
public GUIListBox HeadSelectionList = null;
|
||||||
|
public bool HasIcon = true;
|
||||||
|
|
||||||
|
public GUIScrollBar.OnMovedHandler OnSliderMoved = null;
|
||||||
|
public GUIScrollBar.OnMovedHandler OnSliderReleased = null;
|
||||||
|
public Action<AppearanceCustomizationMenu> OnHeadSwitch = null;
|
||||||
|
|
||||||
|
private readonly GUIComponent parentComponent;
|
||||||
|
private readonly List<Sprite> characterSprites = new List<Sprite>();
|
||||||
|
public GUIButton RandomizeButton;
|
||||||
|
|
||||||
|
public AppearanceCustomizationMenu(CharacterInfo info, GUIComponent parent, bool hasIcon = true)
|
||||||
|
{
|
||||||
|
CharacterInfo = info;
|
||||||
|
parentComponent = parent;
|
||||||
|
HasIcon = hasIcon;
|
||||||
|
|
||||||
|
RecreateFrameContents();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecreateFrameContents()
|
||||||
|
{
|
||||||
|
var info = CharacterInfo;
|
||||||
|
|
||||||
|
HeadSelectionList = null;
|
||||||
|
parentComponent.ClearChildren();
|
||||||
|
ClearSprites();
|
||||||
|
|
||||||
|
float contentWidth = HasIcon ? 0.75f : 1.0f;
|
||||||
|
var listBox = new GUIListBox(
|
||||||
|
new RectTransform(new Vector2(contentWidth, 1.0f), parentComponent.RectTransform,
|
||||||
|
Anchor.CenterLeft))
|
||||||
|
{ CanBeFocused = false, CanTakeKeyBoardFocus = false };
|
||||||
|
var content = listBox.Content;
|
||||||
|
|
||||||
|
info.LoadHeadAttachments();
|
||||||
|
if (HasIcon)
|
||||||
|
{
|
||||||
|
info.CreateIcon(
|
||||||
|
new RectTransform(new Vector2(0.25f, 1.0f), parentComponent.RectTransform, Anchor.CenterRight)
|
||||||
|
{ RelativeOffset = new Vector2(-0.01f, 0.0f) });
|
||||||
|
}
|
||||||
|
|
||||||
|
RectTransform createItemRectTransform(string labelTag, float width = 0.6f)
|
||||||
|
{
|
||||||
|
var layoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.166f), content.RectTransform));
|
||||||
|
|
||||||
|
var label = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), layoutGroup.RectTransform),
|
||||||
|
TextManager.Get(labelTag), font: GUI.SubHeadingFont);
|
||||||
|
|
||||||
|
var bottomItem = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.5f), layoutGroup.RectTransform),
|
||||||
|
style: null);
|
||||||
|
|
||||||
|
return new RectTransform(new Vector2(width, 1.0f), bottomItem.RectTransform, Anchor.Center);
|
||||||
|
}
|
||||||
|
|
||||||
|
RectTransform genderItemRT = createItemRectTransform("Gender", 1.0f);
|
||||||
|
|
||||||
|
GUILayoutGroup genderContainer =
|
||||||
|
new GUILayoutGroup(genderItemRT, isHorizontal: true)
|
||||||
|
{
|
||||||
|
Stretch = true,
|
||||||
|
RelativeSpacing = 0.05f
|
||||||
|
};
|
||||||
|
|
||||||
|
void createGenderButton(Gender gender)
|
||||||
|
{
|
||||||
|
new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), genderContainer.RectTransform),
|
||||||
|
TextManager.Get(gender.ToString()), style: "ListBoxElement")
|
||||||
|
{
|
||||||
|
UserData = gender,
|
||||||
|
OnClicked = OpenHeadSelection,
|
||||||
|
Selected = info.Gender == gender
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
createGenderButton(Gender.Male);
|
||||||
|
createGenderButton(Gender.Female);
|
||||||
|
|
||||||
|
int countAttachmentsOfType(WearableType wearableType)
|
||||||
|
=> info.FilterByTypeAndHeadID(
|
||||||
|
info.FilterElementsByGenderAndRace(info.Wearables, info.Head.gender, info.Head.race),
|
||||||
|
wearableType, info.HeadSpriteId).Count();
|
||||||
|
|
||||||
|
List<GUIScrollBar> attachmentSliders = new List<GUIScrollBar>();
|
||||||
|
void createAttachmentSlider(int initialValue, WearableType wearableType)
|
||||||
|
{
|
||||||
|
int attachmentCount = countAttachmentsOfType(wearableType);
|
||||||
|
if (attachmentCount > 0)
|
||||||
|
{
|
||||||
|
var labelTag = wearableType == WearableType.FaceAttachment
|
||||||
|
? "FaceAttachment.Accessories"
|
||||||
|
: $"FaceAttachment.{wearableType}";
|
||||||
|
var sliderItemRT = createItemRectTransform(labelTag);
|
||||||
|
var slider =
|
||||||
|
new GUIScrollBar(sliderItemRT, style: "GUISlider")
|
||||||
|
{
|
||||||
|
Range = new Vector2(0, attachmentCount),
|
||||||
|
StepValue = 1,
|
||||||
|
OnMoved = (bar, scroll) => SwitchAttachment(bar, wearableType),
|
||||||
|
OnReleased = OnSliderReleased,
|
||||||
|
BarSize = 1.0f / (float)(attachmentCount + 1)
|
||||||
|
};
|
||||||
|
slider.BarScrollValue = initialValue;
|
||||||
|
attachmentSliders.Add(slider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createAttachmentSlider(info.HairIndex, WearableType.Hair);
|
||||||
|
createAttachmentSlider(info.BeardIndex, WearableType.Beard);
|
||||||
|
createAttachmentSlider(info.MoustacheIndex, WearableType.Moustache);
|
||||||
|
createAttachmentSlider(info.FaceAttachmentIndex, WearableType.FaceAttachment);
|
||||||
|
|
||||||
|
void createColorSelector(string labelTag, IEnumerable<(Color Color, float Commonness)> options, Func<Color> getter,
|
||||||
|
Action<Color> setter)
|
||||||
|
{
|
||||||
|
var selectorItemRT = createItemRectTransform(labelTag, 0.4f);
|
||||||
|
var dropdown =
|
||||||
|
new GUIDropDown(selectorItemRT)
|
||||||
|
{ AllowNonText = true };
|
||||||
|
|
||||||
|
var listBoxSize = dropdown.ListBox.RectTransform.RelativeSize;
|
||||||
|
dropdown.ListBox.RectTransform.RelativeSize = new Vector2(listBoxSize.X * 1.75f, listBoxSize.Y);
|
||||||
|
var dropdownButton = dropdown.GetChild<GUIButton>();
|
||||||
|
var buttonFrame =
|
||||||
|
new GUIFrame(
|
||||||
|
new RectTransform(Vector2.One * 0.7f, dropdownButton.RectTransform, Anchor.CenterLeft)
|
||||||
|
{ RelativeOffset = new Vector2(0.05f, 0.0f) }, style: null);
|
||||||
|
Color? previewingColor = null;
|
||||||
|
dropdown.OnSelected = (component, color) =>
|
||||||
|
{
|
||||||
|
previewingColor = null;
|
||||||
|
setter((Color)color);
|
||||||
|
buttonFrame.Color = getter();
|
||||||
|
buttonFrame.HoverColor = getter();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
buttonFrame.Color = getter();
|
||||||
|
buttonFrame.HoverColor = getter();
|
||||||
|
|
||||||
|
dropdown.ListBox.UseGridLayout = true;
|
||||||
|
foreach (var option in options)
|
||||||
|
{
|
||||||
|
var optionElement =
|
||||||
|
new GUIFrame(
|
||||||
|
new RectTransform(new Vector2(0.25f, 1.0f / 3.0f),
|
||||||
|
dropdown.ListBox.Content.RectTransform),
|
||||||
|
style: "ListBoxElement")
|
||||||
|
{
|
||||||
|
UserData = option.Color,
|
||||||
|
CanBeFocused = true
|
||||||
|
};
|
||||||
|
var colorElement =
|
||||||
|
new GUIFrame(
|
||||||
|
new RectTransform(Vector2.One * 0.75f, optionElement.RectTransform, Anchor.Center,
|
||||||
|
scaleBasis: ScaleBasis.Smallest),
|
||||||
|
style: null)
|
||||||
|
{
|
||||||
|
Color = option.Color,
|
||||||
|
HoverColor = option.Color,
|
||||||
|
OutlineColor = Color.Lerp(Color.Black, option.Color, 0.5f),
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var childToSelect = dropdown.ListBox.Content.FindChild(c => (Color)c.UserData == getter());
|
||||||
|
dropdown.Select(dropdown.ListBox.Content.GetChildIndex(childToSelect));
|
||||||
|
|
||||||
|
//The following exists to track mouseover to preview colors before selecting them
|
||||||
|
new GUICustomComponent(new RectTransform(Vector2.One, buttonFrame.RectTransform),
|
||||||
|
onUpdate: (deltaTime, component) =>
|
||||||
|
{
|
||||||
|
if (GUI.MouseOn is GUIFrame { Parent: { } p } hoveredFrame && dropdown.ListBox.Content.IsParentOf(hoveredFrame))
|
||||||
|
{
|
||||||
|
previewingColor ??= getter();
|
||||||
|
Color color = (Color)(dropdown.ListBox.Content.FindChild(c =>
|
||||||
|
c == hoveredFrame || c.IsParentOf(hoveredFrame))?.UserData ?? dropdown.SelectedData ?? getter());
|
||||||
|
setter(color);
|
||||||
|
buttonFrame.Color = getter();
|
||||||
|
buttonFrame.HoverColor = getter();
|
||||||
|
}
|
||||||
|
else if (previewingColor.HasValue)
|
||||||
|
{
|
||||||
|
setter(previewingColor.Value);
|
||||||
|
buttonFrame.Color = getter();
|
||||||
|
buttonFrame.HoverColor = getter();
|
||||||
|
previewingColor = null;
|
||||||
|
}
|
||||||
|
}, onDraw: null)
|
||||||
|
{
|
||||||
|
CanBeFocused = false,
|
||||||
|
Visible = true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (countAttachmentsOfType(WearableType.Hair) > 0)
|
||||||
|
{
|
||||||
|
createColorSelector($"Customization.{nameof(info.HairColor)}", info.HairColors,
|
||||||
|
() => info.HairColor, (color) => info.HairColor = color);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (countAttachmentsOfType(WearableType.Moustache) > 0 ||
|
||||||
|
countAttachmentsOfType(WearableType.Beard) > 0)
|
||||||
|
{
|
||||||
|
createColorSelector($"Customization.{nameof(info.FacialHairColor)}", info.FacialHairColors,
|
||||||
|
() => info.FacialHairColor, (color) => info.FacialHairColor = color);
|
||||||
|
}
|
||||||
|
|
||||||
|
createColorSelector($"Customization.{nameof(info.SkinColor)}", info.SkinColors, () => info.SkinColor,
|
||||||
|
(color) => info.SkinColor = color);
|
||||||
|
|
||||||
|
RandomizeButton = new GUIButton(new RectTransform(Vector2.One * 0.12f,
|
||||||
|
parentComponent.RectTransform,
|
||||||
|
anchor: Anchor.BottomRight, scaleBasis: ScaleBasis.Smallest)
|
||||||
|
{ RelativeOffset = new Vector2(0.01f, 0.005f) }, style: "RandomizeButton")
|
||||||
|
{
|
||||||
|
OnClicked = (button, o) =>
|
||||||
|
{
|
||||||
|
info.Head = new HeadInfo();
|
||||||
|
info.SetGenderAndRace(Rand.RandSync.Unsynced);
|
||||||
|
info.SetColors();
|
||||||
|
|
||||||
|
RecreateFrameContents();
|
||||||
|
info.RefreshHead();
|
||||||
|
OnHeadSwitch?.Invoke(this);
|
||||||
|
attachmentSliders.ForEach(s => OnSliderMoved?.Invoke(s, s.BarScroll));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//force update twice because the listbox is insanely janky
|
||||||
|
//TODO: fix all of the UI :)
|
||||||
|
listBox.ForceUpdate();
|
||||||
|
listBox.ForceUpdate();
|
||||||
|
foreach (var childLayoutGroup in listBox.Content.GetAllChildren<GUILayoutGroup>())
|
||||||
|
{
|
||||||
|
childLayoutGroup.Recalculate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool OpenHeadSelection(GUIButton button, object userData)
|
||||||
|
{
|
||||||
|
Gender selectedGender = (Gender)userData;
|
||||||
|
|
||||||
|
var info = CharacterInfo;
|
||||||
|
|
||||||
|
float characterHeightWidthRatio = info.HeadSprite.size.Y / info.HeadSprite.size.X;
|
||||||
|
HeadSelectionList ??= new GUIListBox(
|
||||||
|
new RectTransform(
|
||||||
|
new Point(parentComponent.Rect.Width,
|
||||||
|
(int)(parentComponent.Rect.Width * characterHeightWidthRatio * 0.6f)), GUI.Canvas)
|
||||||
|
{
|
||||||
|
AbsoluteOffset = new Point(parentComponent.Rect.Right - parentComponent.Rect.Width,
|
||||||
|
button.Rect.Bottom)
|
||||||
|
});
|
||||||
|
HeadSelectionList.Visible = true;
|
||||||
|
HeadSelectionList.Content.ClearChildren();
|
||||||
|
ClearSprites();
|
||||||
|
|
||||||
|
parentComponent.RectTransform.SizeChanged += () =>
|
||||||
|
{
|
||||||
|
if (parentComponent == null || HeadSelectionList?.RectTransform == null || button == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HeadSelectionList.RectTransform.Resize(new Point(parentComponent.Rect.Width,
|
||||||
|
(int)(parentComponent.Rect.Width * characterHeightWidthRatio * 0.6f)));
|
||||||
|
HeadSelectionList.RectTransform.AbsoluteOffset =
|
||||||
|
new Point(parentComponent.Rect.Right - parentComponent.Rect.Width, button.Rect.Bottom);
|
||||||
|
};
|
||||||
|
|
||||||
|
new GUIFrame(
|
||||||
|
new RectTransform(new Vector2(1.25f, 1.25f), HeadSelectionList.RectTransform, Anchor.Center),
|
||||||
|
style: "OuterGlow", color: Color.Black)
|
||||||
|
{
|
||||||
|
UserData = "outerglow",
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
|
||||||
|
GUILayoutGroup row = null;
|
||||||
|
int itemsInRow = 0;
|
||||||
|
|
||||||
|
XElement headElement = info.Ragdoll.MainElement.Elements().FirstOrDefault(e =>
|
||||||
|
e.GetAttributeString("type", "").Equals("head", StringComparison.OrdinalIgnoreCase));
|
||||||
|
XElement headSpriteElement = headElement.Element("sprite");
|
||||||
|
string spritePathWithTags = headSpriteElement.Attribute("texture").Value;
|
||||||
|
|
||||||
|
var characterConfigElement = info.CharacterConfigElement;
|
||||||
|
|
||||||
|
var heads = info.Heads;
|
||||||
|
if (heads != null)
|
||||||
|
{
|
||||||
|
row = null;
|
||||||
|
itemsInRow = 0;
|
||||||
|
foreach (var kvp in heads.Where(kv => kv.Key.Gender == selectedGender))
|
||||||
|
{
|
||||||
|
var headPreset = kvp.Key;
|
||||||
|
Race race = headPreset.Race;
|
||||||
|
int headIndex = headPreset.ID;
|
||||||
|
|
||||||
|
string spritePath = spritePathWithTags
|
||||||
|
.Replace("[GENDER]", selectedGender.ToString().ToLowerInvariant())
|
||||||
|
.Replace("[RACE]", race.ToString().ToLowerInvariant());
|
||||||
|
|
||||||
|
if (!File.Exists(spritePath))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Sprite headSprite = new Sprite(headSpriteElement, "", spritePath);
|
||||||
|
headSprite.SourceRect =
|
||||||
|
new Rectangle(CalculateOffset(headSprite, kvp.Value.ToPoint()),
|
||||||
|
headSprite.SourceRect.Size);
|
||||||
|
characterSprites.Add(headSprite);
|
||||||
|
|
||||||
|
if (itemsInRow >= 4 || row == null)
|
||||||
|
{
|
||||||
|
row = new GUILayoutGroup(
|
||||||
|
new RectTransform(new Vector2(1.0f, 0.333f), HeadSelectionList.Content.RectTransform),
|
||||||
|
true)
|
||||||
|
{
|
||||||
|
UserData = selectedGender,
|
||||||
|
Visible = true
|
||||||
|
};
|
||||||
|
itemsInRow = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var btn = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), row.RectTransform),
|
||||||
|
style: "ListBoxElementSquare")
|
||||||
|
{
|
||||||
|
OutlineColor = Color.White * 0.5f,
|
||||||
|
PressedColor = Color.White * 0.5f,
|
||||||
|
UserData = new Tuple<Gender, Race, int>(selectedGender, race, headIndex),
|
||||||
|
OnClicked = SwitchHead,
|
||||||
|
Selected = selectedGender == info.Gender && race == info.Race && headIndex == info.HeadSpriteId,
|
||||||
|
Visible = true
|
||||||
|
};
|
||||||
|
|
||||||
|
new GUIImage(new RectTransform(Vector2.One, btn.RectTransform), headSprite, scaleToFit: true);
|
||||||
|
itemsInRow++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool SwitchHead(GUIButton button, object obj)
|
||||||
|
{
|
||||||
|
var info = CharacterInfo;
|
||||||
|
Gender gender = ((Tuple<Gender, Race, int>)obj).Item1;
|
||||||
|
Race race = ((Tuple<Gender, Race, int>)obj).Item2;
|
||||||
|
int id = ((Tuple<Gender, Race, int>)obj).Item3;
|
||||||
|
info.Gender = gender;
|
||||||
|
info.Race = race;
|
||||||
|
info.Head.HeadSpriteId = id;
|
||||||
|
RecreateFrameContents();
|
||||||
|
OnHeadSwitch?.Invoke(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool SwitchAttachment(GUIScrollBar scrollBar, WearableType type)
|
||||||
|
{
|
||||||
|
var info = CharacterInfo;
|
||||||
|
int index = (int)scrollBar.BarScrollValue;
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case WearableType.Beard:
|
||||||
|
info.BeardIndex = index;
|
||||||
|
break;
|
||||||
|
case WearableType.FaceAttachment:
|
||||||
|
info.FaceAttachmentIndex = index;
|
||||||
|
break;
|
||||||
|
case WearableType.Hair:
|
||||||
|
info.HairIndex = index;
|
||||||
|
break;
|
||||||
|
case WearableType.Moustache:
|
||||||
|
info.MoustacheIndex = index;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DebugConsole.ThrowError($"Wearable type not implemented: {type}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
info.RefreshHead();
|
||||||
|
OnSliderMoved?.Invoke(scrollBar, scrollBar.BarScroll);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
if (HeadSelectionList != null && PlayerInput.PrimaryMouseButtonDown() &&
|
||||||
|
!GUI.IsMouseOn(HeadSelectionList))
|
||||||
|
{
|
||||||
|
HeadSelectionList.Visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddToGUIUpdateList()
|
||||||
|
{
|
||||||
|
HeadSelectionList?.AddToGUIUpdateList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearSprites()
|
||||||
|
{
|
||||||
|
foreach (Sprite sprite in characterSprites) { sprite.Remove(); }
|
||||||
|
characterSprites.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
ClearSprites();
|
||||||
|
}
|
||||||
|
|
||||||
|
~AppearanceCustomizationMenu()
|
||||||
|
{
|
||||||
|
Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,15 +119,23 @@ namespace Barotrauma
|
|||||||
switch ((NetEntityEvent.Type)extraData[0])
|
switch ((NetEntityEvent.Type)extraData[0])
|
||||||
{
|
{
|
||||||
case NetEntityEvent.Type.InventoryState:
|
case NetEntityEvent.Type.InventoryState:
|
||||||
msg.WriteRangedInteger(0, 0, 3);
|
msg.WriteRangedInteger(0, 0, 4);
|
||||||
Inventory.ClientWrite(msg, extraData);
|
Inventory.ClientWrite(msg, extraData);
|
||||||
break;
|
break;
|
||||||
case NetEntityEvent.Type.Treatment:
|
case NetEntityEvent.Type.Treatment:
|
||||||
msg.WriteRangedInteger(1, 0, 3);
|
msg.WriteRangedInteger(1, 0, 4);
|
||||||
msg.Write(AnimController.Anim == AnimController.Animation.CPR);
|
msg.Write(AnimController.Anim == AnimController.Animation.CPR);
|
||||||
break;
|
break;
|
||||||
case NetEntityEvent.Type.Status:
|
case NetEntityEvent.Type.Status:
|
||||||
msg.WriteRangedInteger(2, 0, 3);
|
msg.WriteRangedInteger(2, 0, 4);
|
||||||
|
break;
|
||||||
|
case NetEntityEvent.Type.UpdateTalents:
|
||||||
|
msg.WriteRangedInteger(3, 0, 4);
|
||||||
|
msg.Write((ushort)characterTalents.Count);
|
||||||
|
foreach (var unlockedTalent in characterTalents)
|
||||||
|
{
|
||||||
|
msg.Write(unlockedTalent.Prefab.UIntIdentifier);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -258,7 +266,7 @@ namespace Barotrauma
|
|||||||
if (readStatus)
|
if (readStatus)
|
||||||
{
|
{
|
||||||
ReadStatus(msg);
|
ReadStatus(msg);
|
||||||
(AIController as EnemyAIController)?.PetBehavior?.ClientRead(msg);
|
AIController?.ClientRead(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.ReadPadBits();
|
msg.ReadPadBits();
|
||||||
@@ -291,7 +299,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case ServerNetObject.ENTITY_EVENT:
|
case ServerNetObject.ENTITY_EVENT:
|
||||||
int eventType = msg.ReadRangedInteger(0, 9);
|
int eventType = msg.ReadRangedInteger(0, 13);
|
||||||
switch (eventType)
|
switch (eventType)
|
||||||
{
|
{
|
||||||
case 0: //NetEntityEvent.Type.InventoryState
|
case 0: //NetEntityEvent.Type.InventoryState
|
||||||
@@ -350,7 +358,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
string skillIdentifier = msg.ReadString();
|
string skillIdentifier = msg.ReadString();
|
||||||
float skillLevel = msg.ReadSingle();
|
float skillLevel = msg.ReadSingle();
|
||||||
info?.SetSkillLevel(skillIdentifier, skillLevel, Position + Vector2.UnitY * 150.0f);
|
info?.SetSkillLevel(skillIdentifier, skillLevel);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4: // NetEntityEvent.Type.SetAttackTarget
|
case 4: // NetEntityEvent.Type.SetAttackTarget
|
||||||
@@ -382,11 +390,12 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
targetLimb = targetCharacter.AnimController.Limbs[targetLimbIndex];
|
targetLimb = targetCharacter.AnimController.Limbs[targetLimbIndex];
|
||||||
}
|
}
|
||||||
if (attackLimb?.attack != null)
|
if (attackLimb?.attack != null && Controlled != this)
|
||||||
{
|
{
|
||||||
if (eventType == 4)
|
if (eventType == 4)
|
||||||
{
|
{
|
||||||
SetAttackTarget(attackLimb, targetEntity, targetSimPos);
|
SetAttackTarget(attackLimb, targetEntity, targetSimPos);
|
||||||
|
PlaySound(CharacterSound.SoundType.Attack, maxInterval: 3);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -450,6 +459,36 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 10: //NetEntityEvent.Type.UpdateExperience
|
||||||
|
int experienceAmount = msg.ReadInt32();
|
||||||
|
info?.SetExperience(experienceAmount);
|
||||||
|
break;
|
||||||
|
case 11: //NetEntityEvent.Type.UpdateTalents:
|
||||||
|
ushort talentCount = msg.ReadUInt16();
|
||||||
|
for (int i = 0; i < talentCount; i++)
|
||||||
|
{
|
||||||
|
bool addedThisRound = msg.ReadBoolean();
|
||||||
|
UInt32 talentIdentifier = msg.ReadUInt32();
|
||||||
|
GiveTalent(talentIdentifier, addedThisRound);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 12: //NetEntityEvent.Type.UpdateMoney:
|
||||||
|
int moneyAmount = msg.ReadInt32();
|
||||||
|
SetMoney(moneyAmount);
|
||||||
|
break;
|
||||||
|
case 13: //NetEntityEvent.Type.UpdatePermanentStats:
|
||||||
|
byte savedStatValueCount = msg.ReadByte();
|
||||||
|
StatTypes statType = (StatTypes)msg.ReadByte();
|
||||||
|
info?.ClearSavedStatValues(statType);
|
||||||
|
for (int i = 0; i < savedStatValueCount; i++)
|
||||||
|
{
|
||||||
|
string statIdentifier = msg.ReadString();
|
||||||
|
float statValue = msg.ReadSingle();
|
||||||
|
bool removeOnDeath = msg.ReadBoolean();
|
||||||
|
info?.ChangeSavedStatValue(statType, statValue, statIdentifier, removeOnDeath, setValue: true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
msg.ReadPadBits();
|
msg.ReadPadBits();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,10 +1,4 @@
|
|||||||
using Microsoft.Xna.Framework;
|
namespace Barotrauma
|
||||||
using System.Collections.Generic;
|
|
||||||
using Barotrauma.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Xml.Linq;
|
|
||||||
|
|
||||||
namespace Barotrauma
|
|
||||||
{
|
{
|
||||||
partial class AfflictionHusk : Affliction
|
partial class AfflictionHusk : Affliction
|
||||||
{
|
{
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -109,6 +109,7 @@ namespace Barotrauma
|
|||||||
private float wetTimer;
|
private float wetTimer;
|
||||||
private float dripParticleTimer;
|
private float dripParticleTimer;
|
||||||
private float deadTimer;
|
private float deadTimer;
|
||||||
|
private Color? randomColor;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Note that different limbs can share the same deformations.
|
/// Note that different limbs can share the same deformations.
|
||||||
@@ -120,6 +121,15 @@ namespace Barotrauma
|
|||||||
public List<SpriteDeformation> ActiveDeformations { get; set; } = new List<SpriteDeformation>();
|
public List<SpriteDeformation> ActiveDeformations { get; set; } = new List<SpriteDeformation>();
|
||||||
|
|
||||||
public Sprite Sprite { get; protected set; }
|
public Sprite Sprite { get; protected set; }
|
||||||
|
public Sprite TintMask { get; protected set; }
|
||||||
|
|
||||||
|
public Sprite HuskMask { get; protected set; }
|
||||||
|
public float TintHighlightThreshold { get; protected set; }
|
||||||
|
public float TintHighlightMultiplier { get; protected set; }
|
||||||
|
|
||||||
|
private SpriteBatch.EffectWithParams tintEffectParams;
|
||||||
|
private SpriteBatch.EffectWithParams huskSpriteParams;
|
||||||
|
|
||||||
|
|
||||||
protected DeformableSprite _deformSprite;
|
protected DeformableSprite _deformSprite;
|
||||||
|
|
||||||
@@ -157,6 +167,12 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Sprite GetActiveSprite(bool excludeConditionalSprites = true)
|
||||||
|
=> excludeConditionalSprites ? (_deformSprite != null ? _deformSprite.Sprite : Sprite)
|
||||||
|
: ActiveSprite;
|
||||||
|
|
||||||
|
public float DefaultSpriteDepth { get; private set; }
|
||||||
|
|
||||||
public WearableSprite HuskSprite { get; private set; }
|
public WearableSprite HuskSprite { get; private set; }
|
||||||
public WearableSprite HerpesSprite { get; private set; }
|
public WearableSprite HerpesSprite { get; private set; }
|
||||||
|
|
||||||
@@ -273,6 +289,7 @@ namespace Barotrauma
|
|||||||
DecorativeSpriteGroups[groupID].Add(decorativeSprite);
|
DecorativeSpriteGroups[groupID].Add(decorativeSprite);
|
||||||
spriteAnimState.Add(decorativeSprite, new SpriteState());
|
spriteAnimState.Add(decorativeSprite, new SpriteState());
|
||||||
}
|
}
|
||||||
|
TintMask = null;
|
||||||
foreach (XElement subElement in element.Elements())
|
foreach (XElement subElement in element.Elements())
|
||||||
{
|
{
|
||||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||||
@@ -299,15 +316,42 @@ namespace Barotrauma
|
|||||||
Deformations.AddRange(deformations);
|
Deformations.AddRange(deformations);
|
||||||
NonConditionalDeformations.AddRange(deformations);
|
NonConditionalDeformations.AddRange(deformations);
|
||||||
break;
|
break;
|
||||||
|
case "randomcolor":
|
||||||
|
randomColor = subElement.GetAttributeColorArray("colors", null)?.GetRandom();
|
||||||
|
if (randomColor.HasValue)
|
||||||
|
{
|
||||||
|
Params.GetSprite().Color = randomColor.Value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case "lightsource":
|
case "lightsource":
|
||||||
LightSource = new LightSource(subElement, GetConditionalTarget())
|
LightSource = new LightSource(subElement, GetConditionalTarget())
|
||||||
{
|
{
|
||||||
ParentBody = body,
|
ParentBody = body,
|
||||||
SpriteScale = Vector2.One * Scale * TextureScale
|
SpriteScale = Vector2.One * Scale * TextureScale
|
||||||
};
|
};
|
||||||
|
if (randomColor.HasValue)
|
||||||
|
{
|
||||||
|
LightSource.Color = new Color(randomColor.Value.R, randomColor.Value.G, randomColor.Value.B, LightSource.Color.A);
|
||||||
|
}
|
||||||
InitialLightSourceColor = LightSource.Color;
|
InitialLightSourceColor = LightSource.Color;
|
||||||
InitialLightSpriteAlpha = LightSource.OverrideLightSpriteAlpha;
|
InitialLightSpriteAlpha = LightSource.OverrideLightSpriteAlpha;
|
||||||
break;
|
break;
|
||||||
|
case "tintmask":
|
||||||
|
string tintMaskPath = subElement.GetAttributeString("texture", "");
|
||||||
|
if (!string.IsNullOrWhiteSpace(tintMaskPath))
|
||||||
|
{
|
||||||
|
TintMask = new Sprite(subElement, file: GetSpritePath(tintMaskPath));
|
||||||
|
TintHighlightThreshold = subElement.GetAttributeFloat("highlightthreshold", 0.6f);
|
||||||
|
TintHighlightMultiplier = subElement.GetAttributeFloat("highlightmultiplier", 0.8f);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "huskmask":
|
||||||
|
string huskMaskPath = subElement.GetAttributeString("texture", "");
|
||||||
|
if (!string.IsNullOrWhiteSpace(huskMaskPath))
|
||||||
|
{
|
||||||
|
HuskMask = new Sprite(subElement, file: GetSpritePath(huskMaskPath));
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ISerializableEntity GetConditionalTarget()
|
ISerializableEntity GetConditionalTarget()
|
||||||
@@ -357,6 +401,7 @@ namespace Barotrauma
|
|||||||
return deformations;
|
return deformations;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DefaultSpriteDepth = GetActiveSprite()?.Depth ?? 0.0f;
|
||||||
LightSource?.CheckConditionals();
|
LightSource?.CheckConditionals();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,20 +494,20 @@ namespace Barotrauma
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the full path of a limb sprite, taking into account tags, gender and head id
|
/// Get the full path of a limb sprite, taking into account tags, gender and head id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private string GetSpritePath(string texturePath)
|
public static string GetSpritePath(string texturePath, CharacterInfo characterInfo)
|
||||||
{
|
{
|
||||||
string spritePath = texturePath;
|
string spritePath = texturePath;
|
||||||
string spritePathWithTags = spritePath;
|
string spritePathWithTags = spritePath;
|
||||||
if (character.Info != null && character.IsHumanoid)
|
if (characterInfo != null)
|
||||||
{
|
{
|
||||||
spritePath = spritePath.Replace("[GENDER]", (character.Info.Gender == Gender.Female) ? "female" : "male");
|
spritePath = spritePath.Replace("[GENDER]", (characterInfo.Gender == Gender.Female) ? "female" : "male");
|
||||||
spritePath = spritePath.Replace("[RACE]", character.Info.Race.ToString().ToLowerInvariant());
|
spritePath = spritePath.Replace("[RACE]", characterInfo.Race.ToString().ToLowerInvariant());
|
||||||
spritePath = spritePath.Replace("[HEADID]", character.Info.HeadSpriteId.ToString());
|
spritePath = spritePath.Replace("[HEADID]", characterInfo.HeadSpriteId.ToString());
|
||||||
|
|
||||||
if (character.Info.HeadSprite != null && character.Info.SpriteTags.Any())
|
if (characterInfo.HeadSprite != null && characterInfo.SpriteTags.Any())
|
||||||
{
|
{
|
||||||
string tags = "";
|
string tags = "";
|
||||||
character.Info.SpriteTags.ForEach(tag => tags += "[" + tag + "]");
|
characterInfo.SpriteTags.ForEach(tag => tags += "[" + tag + "]");
|
||||||
|
|
||||||
spritePathWithTags = Path.Combine(
|
spritePathWithTags = Path.Combine(
|
||||||
Path.GetDirectoryName(spritePath),
|
Path.GetDirectoryName(spritePath),
|
||||||
@@ -472,6 +517,13 @@ namespace Barotrauma
|
|||||||
return File.Exists(spritePathWithTags) ? spritePathWithTags : spritePath;
|
return File.Exists(spritePathWithTags) ? spritePathWithTags : spritePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private string GetSpritePath(string texturePath)
|
||||||
|
{
|
||||||
|
if (!character.IsHumanoid) { return texturePath; }
|
||||||
|
return GetSpritePath(texturePath, character?.Info);
|
||||||
|
}
|
||||||
|
|
||||||
partial void LoadParamsProjSpecific()
|
partial void LoadParamsProjSpecific()
|
||||||
{
|
{
|
||||||
bool isFlipped = dir == Direction.Left;
|
bool isFlipped = dir == Direction.Left;
|
||||||
@@ -538,8 +590,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
foreach (ParticleEmitter emitter in character.DamageEmitters)
|
foreach (ParticleEmitter emitter in character.DamageEmitters)
|
||||||
{
|
{
|
||||||
if (inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Air) { continue; }
|
if (InWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Air) { continue; }
|
||||||
if (!inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Water) { continue; }
|
if (!InWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Water) { continue; }
|
||||||
ParticlePrefab overrideParticle = null;
|
ParticlePrefab overrideParticle = null;
|
||||||
foreach (DamageModifier damageModifier in result.AppliedDamageModifiers)
|
foreach (DamageModifier damageModifier in result.AppliedDamageModifiers)
|
||||||
{
|
{
|
||||||
@@ -560,8 +612,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
foreach (ParticleEmitter emitter in character.BloodEmitters)
|
foreach (ParticleEmitter emitter in character.BloodEmitters)
|
||||||
{
|
{
|
||||||
if (inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Air) { continue; }
|
if (InWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Air) { continue; }
|
||||||
if (!inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Water) { continue; }
|
if (!InWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Water) { continue; }
|
||||||
emitter.Emit(1.0f, WorldPosition, character.CurrentHull, sizeMultiplier: bloodParticleSize, amountMultiplier: bloodParticleAmount);
|
emitter.Emit(1.0f, WorldPosition, character.CurrentHull, sizeMultiplier: bloodParticleSize, amountMultiplier: bloodParticleAmount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -585,7 +637,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inWater)
|
if (InWater)
|
||||||
{
|
{
|
||||||
wetTimer = 1.0f;
|
wetTimer = 1.0f;
|
||||||
}
|
}
|
||||||
@@ -632,19 +684,38 @@ namespace Barotrauma
|
|||||||
RefreshDeformations();
|
RefreshDeformations();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Draw(SpriteBatch spriteBatch, Camera cam, Color? overrideColor = null)
|
public void Draw(SpriteBatch spriteBatch, Camera cam, Color? overrideColor = null, bool disableDeformations = false)
|
||||||
{
|
{
|
||||||
float brightness = 1.0f - (burnOverLayStrength / 100.0f) * 0.5f;
|
float brightness = 1.0f - (burnOverLayStrength / 100.0f) * 0.5f;
|
||||||
var spriteParams = Params.GetSprite();
|
var spriteParams = Params.GetSprite();
|
||||||
if (spriteParams == null) { return; }
|
if (spriteParams == null) { return; }
|
||||||
|
|
||||||
Color color = new Color(spriteParams.Color.R / 255f * brightness, spriteParams.Color.G / 255f * brightness, spriteParams.Color.B / 255f * brightness, spriteParams.Color.A / 255f);
|
Color clr = spriteParams.Color;
|
||||||
|
if (!spriteParams.IgnoreTint)
|
||||||
|
{
|
||||||
|
clr = clr.Multiply(ragdoll.RagdollParams.Color);
|
||||||
|
if (character.Info != null)
|
||||||
|
{
|
||||||
|
clr = clr.Multiply(character.Info.SkinColor);
|
||||||
|
}
|
||||||
|
if (character.CharacterHealth.FaceTint.A > 0 && type == LimbType.Head)
|
||||||
|
{
|
||||||
|
clr = Color.Lerp(clr, character.CharacterHealth.FaceTint.Opaque(), character.CharacterHealth.FaceTint.A / 255.0f);
|
||||||
|
}
|
||||||
|
if (character.CharacterHealth.BodyTint.A > 0)
|
||||||
|
{
|
||||||
|
clr = Color.Lerp(clr, character.CharacterHealth.BodyTint.Opaque(), character.CharacterHealth.BodyTint.A / 255.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Color color = new Color((byte)(clr.R * brightness), (byte)(clr.G * brightness), (byte)(clr.B * brightness), clr.A);
|
||||||
|
Color blankColor = new Color(brightness, brightness, brightness, 1);
|
||||||
if (deadTimer > 0)
|
if (deadTimer > 0)
|
||||||
{
|
{
|
||||||
color = Color.Lerp(color, spriteParams.DeadColor, MathUtils.InverseLerp(0, spriteParams.DeadColorTime, deadTimer));
|
color = Color.Lerp(color, spriteParams.DeadColor, MathUtils.InverseLerp(0, spriteParams.DeadColorTime, deadTimer));
|
||||||
}
|
}
|
||||||
|
|
||||||
color = overrideColor ?? color;
|
color = overrideColor ?? color;
|
||||||
|
blankColor = overrideColor ?? blankColor;
|
||||||
|
|
||||||
if (isSevered)
|
if (isSevered)
|
||||||
{
|
{
|
||||||
@@ -667,6 +738,8 @@ namespace Barotrauma
|
|||||||
OtherWearables.Any(w => w.HideLimb) ||
|
OtherWearables.Any(w => w.HideLimb) ||
|
||||||
wearingItems.Any(w => w != null && w.HideLimb);
|
wearingItems.Any(w => w != null && w.HideLimb);
|
||||||
|
|
||||||
|
bool drawHuskSprite = HuskSprite != null && !wearableTypesToHide.Contains(WearableType.Husk);
|
||||||
|
|
||||||
var activeSprite = ActiveSprite;
|
var activeSprite = ActiveSprite;
|
||||||
if (type == LimbType.Head)
|
if (type == LimbType.Head)
|
||||||
{
|
{
|
||||||
@@ -674,11 +747,12 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
body.UpdateDrawPosition();
|
body.UpdateDrawPosition();
|
||||||
|
float depthStep = 0.000001f;
|
||||||
|
|
||||||
if (!hideLimb)
|
if (!hideLimb)
|
||||||
{
|
{
|
||||||
var deformSprite = DeformSprite;
|
var deformSprite = DeformSprite;
|
||||||
if (deformSprite != null)
|
if (deformSprite != null && !disableDeformations)
|
||||||
{
|
{
|
||||||
if (ActiveDeformations.Any())
|
if (ActiveDeformations.Any())
|
||||||
{
|
{
|
||||||
@@ -698,7 +772,33 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
bool useTintMask = TintMask != null && spriteBatch.GetCurrentEffect() is null;
|
||||||
|
if (useTintMask)
|
||||||
|
{
|
||||||
|
tintEffectParams.Effect ??= GameMain.GameScreen.ThresholdTintEffect;
|
||||||
|
tintEffectParams.Params ??= new Dictionary<string, object>();
|
||||||
|
var parameters = tintEffectParams.Params;
|
||||||
|
parameters["xBaseTexture"] = Sprite.Texture;
|
||||||
|
parameters["xTintMaskTexture"] = TintMask.Texture;
|
||||||
|
if (drawHuskSprite && HuskMask != null)
|
||||||
|
{
|
||||||
|
parameters["xCutoffTexture"] = HuskMask.Texture;
|
||||||
|
parameters["baseToCutoffSizeRatio"] = (float)Sprite.Texture.Width / (float)HuskMask.Texture.Width;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parameters["xCutoffTexture"] = GUI.WhiteTexture;
|
||||||
|
parameters["baseToCutoffSizeRatio"] = 1.0f;
|
||||||
|
}
|
||||||
|
parameters["highlightThreshold"] = TintHighlightThreshold;
|
||||||
|
parameters["highlightMultiplier"] = TintHighlightMultiplier;
|
||||||
|
spriteBatch.SwapEffect(tintEffectParams);
|
||||||
|
}
|
||||||
body.Draw(spriteBatch, activeSprite, color, null, Scale * TextureScale, Params.MirrorHorizontally, Params.MirrorVertically);
|
body.Draw(spriteBatch, activeSprite, color, null, Scale * TextureScale, Params.MirrorHorizontally, Params.MirrorVertically);
|
||||||
|
if (useTintMask)
|
||||||
|
{
|
||||||
|
spriteBatch.SwapEffect(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Handle non-exlusive, i.e. additional conditional sprites
|
// Handle non-exlusive, i.e. additional conditional sprites
|
||||||
foreach (var conditionalSprite in ConditionalSprites)
|
foreach (var conditionalSprite in ConditionalSprites)
|
||||||
@@ -722,7 +822,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
body.Draw(spriteBatch, conditionalSprite.Sprite, color, null, Scale * TextureScale, Params.MirrorHorizontally, Params.MirrorVertically);
|
body.Draw(spriteBatch, conditionalSprite.Sprite, color, depth: activeSprite.Depth - (depthStep * 50), Scale * TextureScale, Params.MirrorHorizontally, Params.MirrorVertically);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -737,7 +837,7 @@ namespace Barotrauma
|
|||||||
new Vector2(body.DrawPosition.X, -body.DrawPosition.Y),
|
new Vector2(body.DrawPosition.X, -body.DrawPosition.Y),
|
||||||
color * Math.Min(damageOverlayStrength, 1.0f), activeSprite.Origin,
|
color * Math.Min(damageOverlayStrength, 1.0f), activeSprite.Origin,
|
||||||
-body.DrawRotation,
|
-body.DrawRotation,
|
||||||
Scale, spriteEffect, activeSprite.Depth - 0.0000015f);
|
Scale, spriteEffect, activeSprite.Depth - (depthStep * 90));
|
||||||
}
|
}
|
||||||
foreach (var decorativeSprite in DecorativeSprites)
|
foreach (var decorativeSprite in DecorativeSprites)
|
||||||
{
|
{
|
||||||
@@ -755,9 +855,8 @@ namespace Barotrauma
|
|||||||
Vector2 transformedOffset = new Vector2(ca * offset.X + sa * offset.Y, -sa * offset.X + ca * offset.Y);
|
Vector2 transformedOffset = new Vector2(ca * offset.X + sa * offset.Y, -sa * offset.X + ca * offset.Y);
|
||||||
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(body.DrawPosition.X + transformedOffset.X, -(body.DrawPosition.Y + transformedOffset.Y)), c,
|
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(body.DrawPosition.X + transformedOffset.X, -(body.DrawPosition.Y + transformedOffset.Y)), c,
|
||||||
-body.Rotation + rotation, decorativeSprite.GetScale(spriteAnimState[decorativeSprite].RandomScaleFactor) * Scale, spriteEffect,
|
-body.Rotation + rotation, decorativeSprite.GetScale(spriteAnimState[decorativeSprite].RandomScaleFactor) * Scale, spriteEffect,
|
||||||
depth: decorativeSprite.Sprite.Depth);
|
depth: activeSprite.Depth - (depthStep * 100));
|
||||||
}
|
}
|
||||||
float depthStep = 0.000001f;
|
|
||||||
float step = depthStep;
|
float step = depthStep;
|
||||||
WearableSprite onlyDrawable = wearingItems.Find(w => w.HideOtherWearables);
|
WearableSprite onlyDrawable = wearingItems.Find(w => w.HideOtherWearables);
|
||||||
if (Params.MirrorHorizontally)
|
if (Params.MirrorHorizontally)
|
||||||
@@ -770,23 +869,44 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
if (onlyDrawable == null)
|
if (onlyDrawable == null)
|
||||||
{
|
{
|
||||||
if (HerpesSprite != null && !wearableTypesToHide.Contains(WearableType.Herpes))
|
if (HerpesSprite != null && !wearableTypesToHide.Contains(WearableType.Herpes) && herpesStrength > 0)
|
||||||
{
|
{
|
||||||
DrawWearable(HerpesSprite, depthStep, spriteBatch, color * Math.Min(herpesStrength / 10.0f, 1.0f), spriteEffect);
|
float alpha = Math.Min(herpesStrength * 2 / 100.0f, 1.0f);
|
||||||
|
DrawWearable(HerpesSprite, depthStep, spriteBatch, blankColor, alpha: alpha, spriteEffect);
|
||||||
|
depthStep += step;
|
||||||
|
}
|
||||||
|
if (drawHuskSprite)
|
||||||
|
{
|
||||||
|
bool useTintEffect = HuskMask != null && spriteBatch.GetCurrentEffect() is null;
|
||||||
|
if (useTintEffect)
|
||||||
|
{
|
||||||
|
huskSpriteParams.Effect ??= GameMain.GameScreen.ThresholdTintEffect;
|
||||||
|
huskSpriteParams.Params ??= new Dictionary<string, object>();
|
||||||
|
var parameters = huskSpriteParams.Params;
|
||||||
|
parameters["xCutoffTexture"] = GUI.WhiteTexture;
|
||||||
|
parameters["baseToCutoffSizeRatio"] = 1.0f;
|
||||||
|
spriteBatch.SwapEffect(huskSpriteParams);
|
||||||
|
}
|
||||||
|
DrawWearable(HuskSprite, depthStep, spriteBatch, color, alpha: color.A / 255f, spriteEffect);
|
||||||
|
if (useTintEffect)
|
||||||
|
{
|
||||||
|
spriteBatch.SwapEffect(null);
|
||||||
|
}
|
||||||
depthStep += step;
|
depthStep += step;
|
||||||
}
|
}
|
||||||
foreach (WearableSprite wearable in OtherWearables)
|
foreach (WearableSprite wearable in OtherWearables)
|
||||||
{
|
{
|
||||||
|
if (wearable.Type == WearableType.Husk) { continue; }
|
||||||
if (wearableTypesToHide.Contains(wearable.Type)) { continue; }
|
if (wearableTypesToHide.Contains(wearable.Type)) { continue; }
|
||||||
DrawWearable(wearable, depthStep, spriteBatch, color, spriteEffect);
|
DrawWearable(wearable, depthStep, spriteBatch, blankColor, alpha: color.A / 255f, spriteEffect);
|
||||||
//if there are multiple sprites on this limb, make the successive ones be drawn in front
|
//if there are multiple sprites on this limb, make the successive ones be drawn in front
|
||||||
depthStep += step;
|
depthStep += step;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (WearableSprite wearable in WearingItems)
|
foreach (WearableSprite wearable in WearingItems)
|
||||||
{
|
{
|
||||||
if (onlyDrawable != null && onlyDrawable != wearable) continue;
|
if (onlyDrawable != null && onlyDrawable != wearable && wearable.CanBeHiddenByOtherWearables) { continue; }
|
||||||
DrawWearable(wearable, depthStep, spriteBatch, color, spriteEffect);
|
DrawWearable(wearable, depthStep, spriteBatch, blankColor, alpha: color.A / 255f, spriteEffect);
|
||||||
//if there are multiple sprites on this limb, make the successive ones be drawn in front
|
//if there are multiple sprites on this limb, make the successive ones be drawn in front
|
||||||
depthStep += step;
|
depthStep += step;
|
||||||
}
|
}
|
||||||
@@ -936,7 +1056,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawWearable(WearableSprite wearable, float depthStep, SpriteBatch spriteBatch, Color color, SpriteEffects spriteEffect)
|
private void DrawWearable(WearableSprite wearable, float depthStep, SpriteBatch spriteBatch, Color color, float alpha, SpriteEffects spriteEffect)
|
||||||
{
|
{
|
||||||
var sprite = ActiveSprite;
|
var sprite = ActiveSprite;
|
||||||
if (wearable.InheritSourceRect)
|
if (wearable.InheritSourceRect)
|
||||||
@@ -955,7 +1075,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2 origin = wearable.Sprite.Origin;
|
Vector2 origin;
|
||||||
if (wearable.InheritOrigin)
|
if (wearable.InheritOrigin)
|
||||||
{
|
{
|
||||||
origin = sprite.Origin;
|
origin = sprite.Origin;
|
||||||
@@ -986,24 +1106,49 @@ namespace Barotrauma
|
|||||||
Color wearableColor = Color.White;
|
Color wearableColor = Color.White;
|
||||||
if (wearableItemComponent != null)
|
if (wearableItemComponent != null)
|
||||||
{
|
{
|
||||||
// Draw outer cloths on top of inner cloths.
|
// Draw outer clothes on top of inner clothes.
|
||||||
if (wearableItemComponent.AllowedSlots.Contains(InvSlotType.OuterClothes))
|
if (wearableItemComponent.AllowedSlots.Contains(InvSlotType.OuterClothes))
|
||||||
{
|
{
|
||||||
depth -= depthStep;
|
depth -= depthStep;
|
||||||
}
|
}
|
||||||
if (wearableItemComponent.AllowedSlots.Contains(InvSlotType.Bag))
|
if (wearableItemComponent.AllowedSlots.Contains(InvSlotType.Bag))
|
||||||
{
|
{
|
||||||
depth -= depthStep * 2;
|
depth -= depthStep * 4;
|
||||||
}
|
}
|
||||||
wearableColor = wearableItemComponent.Item.GetSpriteColor();
|
wearableColor = wearableItemComponent.Item.GetSpriteColor();
|
||||||
}
|
}
|
||||||
float textureScale = wearable.InheritTextureScale ? TextureScale : wearable.Scale;
|
else if (character.Info != null)
|
||||||
|
{
|
||||||
wearable.Sprite.Draw(spriteBatch,
|
if (wearable.Type == WearableType.Hair)
|
||||||
new Vector2(body.DrawPosition.X, -body.DrawPosition.Y),
|
{
|
||||||
new Color((color.R * wearableColor.R) / (255.0f * 255.0f), (color.G * wearableColor.G) / (255.0f * 255.0f), (color.B * wearableColor.B) / (255.0f * 255.0f)) * ((color.A * wearableColor.A) / (255.0f * 255.0f)),
|
wearableColor = character.Info.HairColor;
|
||||||
origin, -body.DrawRotation,
|
}
|
||||||
Scale * textureScale, spriteEffect, depth);
|
else if (wearable.Type == WearableType.Beard || wearable.Type == WearableType.Moustache)
|
||||||
|
{
|
||||||
|
wearableColor = character.Info.FacialHairColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
float scale = wearable.Scale;
|
||||||
|
if (wearable.InheritScale)
|
||||||
|
{
|
||||||
|
if (!wearable.IgnoreTextureScale)
|
||||||
|
{
|
||||||
|
scale *= TextureScale;
|
||||||
|
}
|
||||||
|
if (!wearable.IgnoreLimbScale)
|
||||||
|
{
|
||||||
|
scale *= Params.Scale;
|
||||||
|
}
|
||||||
|
if (!wearable.IgnoreRagdollScale)
|
||||||
|
{
|
||||||
|
scale *= ragdoll.RagdollParams.LimbScale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
float rotation = -body.DrawRotation - wearable.Rotation * Dir;
|
||||||
|
float finalAlpha = alpha * wearableColor.A;
|
||||||
|
Color finalColor = color.Multiply(wearableColor);
|
||||||
|
finalColor = new Color(finalColor.R, finalColor.G, finalColor.B, (byte)finalAlpha);
|
||||||
|
wearable.Sprite.Draw(spriteBatch, new Vector2(body.DrawPosition.X, -body.DrawPosition.Y), finalColor, origin, rotation, scale, spriteEffect, depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
private WearableSprite GetWearableSprite(WearableType type, bool random = false)
|
private WearableSprite GetWearableSprite(WearableType type, bool random = false)
|
||||||
@@ -1054,6 +1199,9 @@ namespace Barotrauma
|
|||||||
|
|
||||||
HerpesSprite?.Sprite.Remove();
|
HerpesSprite?.Sprite.Remove();
|
||||||
HerpesSprite = null;
|
HerpesSprite = null;
|
||||||
|
|
||||||
|
TintMask?.Remove();
|
||||||
|
TintMask = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -418,14 +418,14 @@ namespace Barotrauma
|
|||||||
ShowQuestionPrompt("The automatic hull generation may not work correctly if your submarine uses curved walls. Do you want to continue? Y/N",
|
ShowQuestionPrompt("The automatic hull generation may not work correctly if your submarine uses curved walls. Do you want to continue? Y/N",
|
||||||
(option2) =>
|
(option2) =>
|
||||||
{
|
{
|
||||||
if (option2.ToLower() == "y") { GameMain.SubEditorScreen.AutoHull(); }
|
if (option2.ToLowerInvariant() == "y") { GameMain.SubEditorScreen.AutoHull(); }
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ShowQuestionPrompt("The automatic hull generation may not work correctly if your submarine uses curved walls. Do you want to continue? Y/N",
|
ShowQuestionPrompt("The automatic hull generation may not work correctly if your submarine uses curved walls. Do you want to continue? Y/N",
|
||||||
(option) => { if (option.ToLower() == "y") GameMain.SubEditorScreen.AutoHull(); });
|
(option) => { if (option.ToLowerInvariant() == "y") GameMain.SubEditorScreen.AutoHull(); });
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -476,6 +476,7 @@ namespace Barotrauma
|
|||||||
if (Screen.Selected == GameMain.SubEditorScreen)
|
if (Screen.Selected == GameMain.SubEditorScreen)
|
||||||
{
|
{
|
||||||
NewMessage("WARNING: Switching directly from the submarine editor to the game view may cause bugs and crashes. Use with caution.", Color.Orange);
|
NewMessage("WARNING: Switching directly from the submarine editor to the game view may cause bugs and crashes. Use with caution.", Color.Orange);
|
||||||
|
Entity.Spawner ??= new EntitySpawner();
|
||||||
}
|
}
|
||||||
GameMain.GameScreen.Select();
|
GameMain.GameScreen.Select();
|
||||||
}));
|
}));
|
||||||
@@ -488,6 +489,8 @@ namespace Barotrauma
|
|||||||
Submarine.MainSub = Submarine.Load(subInfo, true);
|
Submarine.MainSub = Submarine.Load(subInfo, true);
|
||||||
}
|
}
|
||||||
GameMain.SubEditorScreen.Select(enableAutoSave: Screen.Selected != GameMain.GameScreen);
|
GameMain.SubEditorScreen.Select(enableAutoSave: Screen.Selected != GameMain.GameScreen);
|
||||||
|
Entity.Spawner?.Remove();
|
||||||
|
Entity.Spawner = null;
|
||||||
}, isCheat: true));
|
}, isCheat: true));
|
||||||
|
|
||||||
commands.Add(new Command("editparticles|particleeditor", "editparticles/particleeditor: Switch to the Particle Editor to edit particle effects.", (string[] args) =>
|
commands.Add(new Command("editparticles|particleeditor", "editparticles/particleeditor: Switch to the Particle Editor to edit particle effects.", (string[] args) =>
|
||||||
@@ -608,7 +611,7 @@ namespace Barotrauma
|
|||||||
ShowQuestionPrompt($"Some keybinds may render the game unusable, are you sure you want to make these keybinds persistent? ({Keybinds.Count} keybind(s) assigned) Y/N",
|
ShowQuestionPrompt($"Some keybinds may render the game unusable, are you sure you want to make these keybinds persistent? ({Keybinds.Count} keybind(s) assigned) Y/N",
|
||||||
(option2) =>
|
(option2) =>
|
||||||
{
|
{
|
||||||
if (option2.ToLower() != "y")
|
if (option2.ToLowerInvariant() != "y")
|
||||||
{
|
{
|
||||||
NewMessage("Aborted.", GUI.Style.Red);
|
NewMessage("Aborted.", GUI.Style.Red);
|
||||||
return;
|
return;
|
||||||
@@ -689,9 +692,18 @@ namespace Barotrauma
|
|||||||
AssignRelayToServer("setskill", true);
|
AssignRelayToServer("setskill", true);
|
||||||
AssignRelayToServer("readycheck", true);
|
AssignRelayToServer("readycheck", true);
|
||||||
|
|
||||||
|
AssignRelayToServer("givetalent", true);
|
||||||
|
AssignRelayToServer("unlocktalents", true);
|
||||||
|
AssignRelayToServer("giveexperience", true);
|
||||||
|
|
||||||
AssignOnExecute("control", (string[] args) =>
|
AssignOnExecute("control", (string[] args) =>
|
||||||
{
|
{
|
||||||
if (args.Length < 1) return;
|
if (args.Length < 1) { return; }
|
||||||
|
if (GameMain.NetworkMember != null)
|
||||||
|
{
|
||||||
|
GameMain.Client?.SendConsoleCommand("control " + string.Join(' ', args[0]));
|
||||||
|
return;
|
||||||
|
}
|
||||||
var character = FindMatchingCharacter(args, true);
|
var character = FindMatchingCharacter(args, true);
|
||||||
if (character != null)
|
if (character != null)
|
||||||
{
|
{
|
||||||
@@ -1096,9 +1108,35 @@ namespace Barotrauma
|
|||||||
|
|
||||||
commands.Add(new Command("load|loadsub", "load [submarine name]: Load a submarine.", (string[] args) =>
|
commands.Add(new Command("load|loadsub", "load [submarine name]: Load a submarine.", (string[] args) =>
|
||||||
{
|
{
|
||||||
if (args.Length == 0) return;
|
if (args.Length == 0) { return; }
|
||||||
SubmarineInfo subInfo = new SubmarineInfo(string.Join(" ", args));
|
|
||||||
|
if (GameMain.GameSession != null)
|
||||||
|
{
|
||||||
|
ThrowError("The loadsub command cannot be used when a round is running. You should probably be using spawnsub instead.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string name = string.Join(" ", args);
|
||||||
|
SubmarineInfo subInfo = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => name.Equals(s.Name, StringComparison.OrdinalIgnoreCase));
|
||||||
|
if (subInfo == null)
|
||||||
|
{
|
||||||
|
string path = Path.Combine(SubmarineInfo.SavePath, name);
|
||||||
|
if (!File.Exists(path))
|
||||||
|
{
|
||||||
|
ThrowError($"Could not find a submarine with the name \"{name}\" or in the path {path}.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
subInfo = new SubmarineInfo(path);
|
||||||
|
}
|
||||||
|
|
||||||
Submarine.Load(subInfo, true);
|
Submarine.Load(subInfo, true);
|
||||||
|
},
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
return new string[][]
|
||||||
|
{
|
||||||
|
SubmarineInfo.SavedSubmarines.Select(s => s.Name).ToArray()
|
||||||
|
};
|
||||||
}));
|
}));
|
||||||
|
|
||||||
commands.Add(new Command("cleansub", "", (string[] args) =>
|
commands.Add(new Command("cleansub", "", (string[] args) =>
|
||||||
@@ -1317,11 +1355,13 @@ namespace Barotrauma
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float avgOutCondition = (deconstructItem.OutConditionMin + deconstructItem.OutConditionMax) / 2;
|
||||||
|
|
||||||
int? deconstructProductPrice = targetItem.GetMinPrice();
|
int? deconstructProductPrice = targetItem.GetMinPrice();
|
||||||
if (deconstructProductPrice.HasValue)
|
if (deconstructProductPrice.HasValue)
|
||||||
{
|
{
|
||||||
if (!deconstructProductCost.HasValue) { deconstructProductCost = 0; }
|
if (!deconstructProductCost.HasValue) { deconstructProductCost = 0; }
|
||||||
deconstructProductCost += (int)(deconstructProductPrice * deconstructItem.OutCondition);
|
deconstructProductCost += (int)(deconstructProductPrice * avgOutCondition);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fabricationRecipe != null)
|
if (fabricationRecipe != null)
|
||||||
@@ -1331,9 +1371,9 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
NewMessage("Deconstructing \"" + itemPrefab.Name + "\" produces \"" + deconstructItem.ItemIdentifier + "\", which isn't required in the fabrication recipe of the item.", Color.Red);
|
NewMessage("Deconstructing \"" + itemPrefab.Name + "\" produces \"" + deconstructItem.ItemIdentifier + "\", which isn't required in the fabrication recipe of the item.", Color.Red);
|
||||||
}
|
}
|
||||||
else if (ingredient.UseCondition && ingredient.MinCondition < deconstructItem.OutCondition)
|
else if (ingredient.UseCondition && ingredient.MinCondition < avgOutCondition)
|
||||||
{
|
{
|
||||||
NewMessage($"Deconstructing \"{itemPrefab.Name}\" produces more \"{deconstructItem.ItemIdentifier}\", than what's required to fabricate the item (required: {targetItem.Name} {(int)(ingredient.MinCondition * 100)}%, output: {deconstructItem.ItemIdentifier} {(int)(deconstructItem.OutCondition * 100)}%)", Color.Red);
|
NewMessage($"Deconstructing \"{itemPrefab.Name}\" produces more \"{deconstructItem.ItemIdentifier}\", than what's required to fabricate the item (required: {targetItem.Name} {(int)(ingredient.MinCondition * 100)}%, output: {deconstructItem.ItemIdentifier} {(int)(avgOutCondition * 100)}%)", Color.Red);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1692,13 +1732,14 @@ namespace Barotrauma
|
|||||||
//check missing mission texts
|
//check missing mission texts
|
||||||
foreach (var missionPrefab in MissionPrefab.List)
|
foreach (var missionPrefab in MissionPrefab.List)
|
||||||
{
|
{
|
||||||
string nameIdentifier = "missionname." + missionPrefab.Identifier;
|
string missionId = (missionPrefab.ConfigElement.Attribute("textidentifier") == null ? missionPrefab.Identifier : missionPrefab.ConfigElement.GetAttributeString("textidentifier", string.Empty));
|
||||||
|
string nameIdentifier = "missionname." + missionId;
|
||||||
if (!tags[language].Contains(nameIdentifier))
|
if (!tags[language].Contains(nameIdentifier))
|
||||||
{
|
{
|
||||||
if (!missingTags.ContainsKey(nameIdentifier)) { missingTags[nameIdentifier] = new HashSet<string>(); }
|
if (!missingTags.ContainsKey(nameIdentifier)) { missingTags[nameIdentifier] = new HashSet<string>(); }
|
||||||
missingTags[nameIdentifier].Add(language);
|
missingTags[nameIdentifier].Add(language);
|
||||||
}
|
}
|
||||||
string descriptionIdentifier = "missiondescription." + missionPrefab.Identifier;
|
string descriptionIdentifier = "missiondescription." + missionId;
|
||||||
if (!tags[language].Contains(descriptionIdentifier))
|
if (!tags[language].Contains(descriptionIdentifier))
|
||||||
{
|
{
|
||||||
if (!missingTags.ContainsKey(descriptionIdentifier)) { missingTags[descriptionIdentifier] = new HashSet<string>(); }
|
if (!missingTags.ContainsKey(descriptionIdentifier)) { missingTags[descriptionIdentifier] = new HashSet<string>(); }
|
||||||
@@ -1708,6 +1749,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
foreach (SubmarineInfo sub in SubmarineInfo.SavedSubmarines)
|
foreach (SubmarineInfo sub in SubmarineInfo.SavedSubmarines)
|
||||||
{
|
{
|
||||||
|
if (sub.Type != SubmarineType.Player) { continue; }
|
||||||
string nameIdentifier = "submarine.name." + sub.Name.ToLowerInvariant();
|
string nameIdentifier = "submarine.name." + sub.Name.ToLowerInvariant();
|
||||||
if (!tags[language].Contains(nameIdentifier))
|
if (!tags[language].Contains(nameIdentifier))
|
||||||
{
|
{
|
||||||
@@ -1724,14 +1766,23 @@ namespace Barotrauma
|
|||||||
|
|
||||||
foreach (AfflictionPrefab affliction in AfflictionPrefab.List)
|
foreach (AfflictionPrefab affliction in AfflictionPrefab.List)
|
||||||
{
|
{
|
||||||
string nameIdentifier = "afflictionname." + affliction.Identifier;
|
if (affliction.ShowIconThreshold > affliction.MaxStrength &&
|
||||||
|
affliction.ShowIconToOthersThreshold > affliction.MaxStrength &&
|
||||||
|
affliction.ShowInHealthScannerThreshold > affliction.MaxStrength)
|
||||||
|
{
|
||||||
|
//hidden affliction, no need for localization
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
string afflictionId = affliction.TranslationOverride ?? affliction.Identifier;
|
||||||
|
string nameIdentifier = "afflictionname." + afflictionId;
|
||||||
if (!tags[language].Contains(nameIdentifier))
|
if (!tags[language].Contains(nameIdentifier))
|
||||||
{
|
{
|
||||||
if (!missingTags.ContainsKey(nameIdentifier)) { missingTags[nameIdentifier] = new HashSet<string>(); }
|
if (!missingTags.ContainsKey(nameIdentifier)) { missingTags[nameIdentifier] = new HashSet<string>(); }
|
||||||
missingTags[nameIdentifier].Add(language);
|
missingTags[nameIdentifier].Add(language);
|
||||||
}
|
}
|
||||||
|
|
||||||
string descriptionIdentifier = "afflictiondescription." + affliction.Identifier;
|
string descriptionIdentifier = "afflictiondescription." + afflictionId;
|
||||||
if (!tags[language].Contains(descriptionIdentifier))
|
if (!tags[language].Contains(descriptionIdentifier))
|
||||||
{
|
{
|
||||||
if (!missingTags.ContainsKey(descriptionIdentifier)) { missingTags[descriptionIdentifier] = new HashSet<string>(); }
|
if (!missingTags.ContainsKey(descriptionIdentifier)) { missingTags[descriptionIdentifier] = new HashSet<string>(); }
|
||||||
@@ -1739,6 +1790,29 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var talentTree in TalentTree.JobTalentTrees)
|
||||||
|
{
|
||||||
|
foreach (var talentSubTree in talentTree.Value.TalentSubTrees)
|
||||||
|
{
|
||||||
|
string nameIdentifier = "talenttree." + talentSubTree.Identifier;
|
||||||
|
if (!tags[language].Contains(nameIdentifier))
|
||||||
|
{
|
||||||
|
if (!missingTags.ContainsKey(nameIdentifier)) { missingTags[nameIdentifier] = new HashSet<string>(); }
|
||||||
|
missingTags[nameIdentifier].Add(language);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var talent in TalentPrefab.TalentPrefabs)
|
||||||
|
{
|
||||||
|
string nameIdentifier = "talentname." + talent.Identifier;
|
||||||
|
if (!tags[language].Contains(nameIdentifier))
|
||||||
|
{
|
||||||
|
if (!missingTags.ContainsKey(nameIdentifier)) { missingTags[nameIdentifier] = new HashSet<string>(); }
|
||||||
|
missingTags[nameIdentifier].Add(language);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//check missing entity names
|
//check missing entity names
|
||||||
foreach (MapEntityPrefab me in MapEntityPrefab.List)
|
foreach (MapEntityPrefab me in MapEntityPrefab.List)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public override void ClientReadInitial(IReadMessage msg)
|
public override void ClientReadInitial(IReadMessage msg)
|
||||||
{
|
{
|
||||||
|
base.ClientReadInitial(msg);
|
||||||
ushort targetItemCount = msg.ReadUInt16();
|
ushort targetItemCount = msg.ReadUInt16();
|
||||||
for (int i = 0; i < targetItemCount; i++)
|
for (int i = 0; i < targetItemCount; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
using Barotrauma.Networking;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
partial class AlienRuinMission : Mission
|
||||||
|
{
|
||||||
|
public override void ClientReadInitial(IReadMessage msg)
|
||||||
|
{
|
||||||
|
base.ClientReadInitial(msg);
|
||||||
|
existingTargets.Clear();
|
||||||
|
spawnedTargets.Clear();
|
||||||
|
allTargets.Clear();
|
||||||
|
ushort existingTargetsCount = msg.ReadUInt16();
|
||||||
|
for (int i = 0; i < existingTargetsCount; i++)
|
||||||
|
{
|
||||||
|
ushort targetId = msg.ReadUInt16();
|
||||||
|
if (targetId == Entity.NullEntityID) { continue; }
|
||||||
|
Entity target = Entity.FindEntityByID(targetId);
|
||||||
|
if (target == null) { continue; }
|
||||||
|
existingTargets.Add(target);
|
||||||
|
allTargets.Add(target);
|
||||||
|
}
|
||||||
|
ushort spawnedTargetsCount = msg.ReadUInt16();
|
||||||
|
for (int i = 0; i < spawnedTargetsCount; i++)
|
||||||
|
{
|
||||||
|
var enemy = Character.ReadSpawnData(msg);
|
||||||
|
existingTargets.Add(enemy);
|
||||||
|
allTargets.Add(enemy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
using Barotrauma.Networking;
|
|
||||||
|
|
||||||
namespace Barotrauma
|
|
||||||
{
|
|
||||||
partial class BeaconMission : Mission
|
|
||||||
{
|
|
||||||
public override void ClientReadInitial(IReadMessage msg)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -25,6 +25,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
public override void ClientReadInitial(IReadMessage msg)
|
public override void ClientReadInitial(IReadMessage msg)
|
||||||
{
|
{
|
||||||
|
base.ClientReadInitial(msg);
|
||||||
items.Clear();
|
items.Clear();
|
||||||
ushort itemCount = msg.ReadUInt16();
|
ushort itemCount = msg.ReadUInt16();
|
||||||
for (int i = 0; i < itemCount; i++)
|
for (int i = 0; i < itemCount; i++)
|
||||||
|
|||||||
@@ -20,10 +20,5 @@ namespace Barotrauma
|
|||||||
return descriptions[GameMain.Client.Character.TeamID == CharacterTeamType.Team1 ? 1 : 2];
|
return descriptions[GameMain.Client.Character.TeamID == CharacterTeamType.Team1 ? 1 : 2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ClientReadInitial(IReadMessage msg)
|
|
||||||
{
|
|
||||||
//do nothing
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
public override void ClientReadInitial(IReadMessage msg)
|
public override void ClientReadInitial(IReadMessage msg)
|
||||||
{
|
{
|
||||||
|
base.ClientReadInitial(msg);
|
||||||
|
|
||||||
byte characterCount = msg.ReadByte();
|
byte characterCount = msg.ReadByte();
|
||||||
|
|
||||||
for (int i = 0; i < characterCount; i++)
|
for (int i = 0; i < characterCount; i++)
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
public override void ClientReadInitial(IReadMessage msg)
|
public override void ClientReadInitial(IReadMessage msg)
|
||||||
{
|
{
|
||||||
|
base.ClientReadInitial(msg);
|
||||||
byte caveCount = msg.ReadByte();
|
byte caveCount = msg.ReadByte();
|
||||||
for (int i = 0; i < caveCount; i++)
|
for (int i = 0; i < caveCount; i++)
|
||||||
{
|
{
|
||||||
@@ -29,7 +30,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < ResourceClusters.Count; i++)
|
for (int i = 0; i < resourceClusters.Count; i++)
|
||||||
{
|
{
|
||||||
var amount = msg.ReadByte();
|
var amount = msg.ReadByte();
|
||||||
var rotation = msg.ReadSingle();
|
var rotation = msg.ReadSingle();
|
||||||
@@ -41,20 +42,20 @@ namespace Barotrauma
|
|||||||
h.AttachToWall();
|
h.AttachToWall();
|
||||||
item.Rotation = rotation;
|
item.Rotation = rotation;
|
||||||
}
|
}
|
||||||
if (SpawnedResources.TryGetValue(item.Prefab.Identifier, out var resources))
|
if (spawnedResources.TryGetValue(item.Prefab.Identifier, out var resources))
|
||||||
{
|
{
|
||||||
resources.Add(item);
|
resources.Add(item);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SpawnedResources.Add(item.Prefab.Identifier, new List<Item>() { item });
|
spawnedResources.Add(item.Prefab.Identifier, new List<Item>() { item });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CalculateMissionClusterPositions();
|
CalculateMissionClusterPositions();
|
||||||
|
|
||||||
for(int i = 0; i < ResourceClusters.Count; i++)
|
for(int i = 0; i < resourceClusters.Count; i++)
|
||||||
{
|
{
|
||||||
var identifier = msg.ReadString();
|
var identifier = msg.ReadString();
|
||||||
var count = msg.ReadByte();
|
var count = msg.ReadByte();
|
||||||
@@ -66,7 +67,7 @@ namespace Barotrauma
|
|||||||
if (!(entity is Item item)) { continue; }
|
if (!(entity is Item item)) { continue; }
|
||||||
resources[j] = item;
|
resources[j] = item;
|
||||||
}
|
}
|
||||||
RelevantLevelResources.Add(identifier, resources);
|
relevantLevelResources.Add(identifier, resources);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Microsoft.Xna.Framework;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -14,6 +15,10 @@ namespace Barotrauma
|
|||||||
get { return shownMessages; }
|
get { return shownMessages; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool DisplayTargetHudIcons => Prefab.DisplayTargetHudIcons;
|
||||||
|
|
||||||
|
public virtual IEnumerable<Entity> HudIconTargets => Enumerable.Empty<Entity>();
|
||||||
|
|
||||||
public Color GetDifficultyColor()
|
public Color GetDifficultyColor()
|
||||||
{
|
{
|
||||||
int v = Difficulty ?? MissionPrefab.MinDifficulty;
|
int v = Difficulty ?? MissionPrefab.MinDifficulty;
|
||||||
@@ -92,11 +97,14 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(IReadMessage msg)
|
public virtual void ClientRead(IReadMessage msg)
|
||||||
{
|
{
|
||||||
State = msg.ReadInt16();
|
State = msg.ReadInt16();
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void ClientReadInitial(IReadMessage msg);
|
public virtual void ClientReadInitial(IReadMessage msg)
|
||||||
|
{
|
||||||
|
state = msg.ReadInt16();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,13 +18,54 @@ namespace Barotrauma
|
|||||||
private set;
|
private set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool DisplayTargetHudIcons
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float HudIconMaxDistance
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Sprite HudIcon
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return hudIcon ?? Icon;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color HudIconColor
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return hudIconColor ?? IconColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Sprite hudIcon;
|
||||||
|
private Color? hudIconColor;
|
||||||
|
|
||||||
partial void InitProjSpecific(XElement element)
|
partial void InitProjSpecific(XElement element)
|
||||||
{
|
{
|
||||||
|
DisplayTargetHudIcons = element.GetAttributeBool("displaytargethudicons", false);
|
||||||
|
HudIconMaxDistance = element.GetAttributeFloat("hudiconmaxdistance", 1000.0f);
|
||||||
foreach (XElement subElement in element.Elements())
|
foreach (XElement subElement in element.Elements())
|
||||||
{
|
{
|
||||||
if (!subElement.Name.ToString().Equals("icon", StringComparison.OrdinalIgnoreCase)) { continue; }
|
string name = subElement.Name.ToString();
|
||||||
Icon = new Sprite(subElement);
|
if (name.Equals("icon", StringComparison.OrdinalIgnoreCase))
|
||||||
IconColor = subElement.GetAttributeColor("color", Color.White);
|
{
|
||||||
|
Icon = new Sprite(subElement);
|
||||||
|
IconColor = subElement.GetAttributeColor("color", Color.White);
|
||||||
|
}
|
||||||
|
else if (name.Equals("hudicon", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
hudIcon = new Sprite(subElement);
|
||||||
|
hudIconColor = subElement.GetAttributeColor("color");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
public override void ClientReadInitial(IReadMessage msg)
|
public override void ClientReadInitial(IReadMessage msg)
|
||||||
{
|
{
|
||||||
|
base.ClientReadInitial(msg);
|
||||||
byte monsterCount = msg.ReadByte();
|
byte monsterCount = msg.ReadByte();
|
||||||
for (int i = 0; i < monsterCount; i++)
|
for (int i = 0; i < monsterCount; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
public override void ClientReadInitial(IReadMessage msg)
|
public override void ClientReadInitial(IReadMessage msg)
|
||||||
{
|
{
|
||||||
|
base.ClientReadInitial(msg);
|
||||||
byte selectedCaveIndex = msg.ReadByte();
|
byte selectedCaveIndex = msg.ReadByte();
|
||||||
nestPosition = new Vector2(
|
nestPosition = new Vector2(
|
||||||
msg.ReadSingle(),
|
msg.ReadSingle(),
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
public override void ClientReadInitial(IReadMessage msg)
|
public override void ClientReadInitial(IReadMessage msg)
|
||||||
{
|
{
|
||||||
|
base.ClientReadInitial(msg);
|
||||||
// duplicate code from escortmission, should possibly be combined, though additional loot items might be added so maybe not
|
// duplicate code from escortmission, should possibly be combined, though additional loot items might be added so maybe not
|
||||||
byte characterCount = msg.ReadByte();
|
byte characterCount = msg.ReadByte();
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
public override void ClientReadInitial(IReadMessage msg)
|
public override void ClientReadInitial(IReadMessage msg)
|
||||||
{
|
{
|
||||||
|
base.ClientReadInitial(msg);
|
||||||
bool usedExistingItem = msg.ReadBoolean();
|
bool usedExistingItem = msg.ReadBoolean();
|
||||||
if (usedExistingItem)
|
if (usedExistingItem)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
using Barotrauma.Networking;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
partial class ScanMission : Mission
|
||||||
|
{
|
||||||
|
public override IEnumerable<Entity> HudIconTargets
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (State == 0)
|
||||||
|
{
|
||||||
|
return scanTargets.Where(kvp => !kvp.Value).Select(kvp => kvp.Key);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Enumerable.Empty<Entity>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ClientReadInitial(IReadMessage msg)
|
||||||
|
{
|
||||||
|
base.ClientReadInitial(msg);
|
||||||
|
startingItems.Clear();
|
||||||
|
ushort itemCount = msg.ReadUInt16();
|
||||||
|
for (int i = 0; i < itemCount; i++)
|
||||||
|
{
|
||||||
|
startingItems.Add(Item.ReadSpawnData(msg));
|
||||||
|
}
|
||||||
|
if (startingItems.Contains(null))
|
||||||
|
{
|
||||||
|
throw new Exception($"Error in ScanMission.ClientReadInitial: item list contains null (mission: {Prefab.Identifier})");
|
||||||
|
}
|
||||||
|
if (startingItems.Count != itemCount)
|
||||||
|
{
|
||||||
|
throw new Exception($"Error in ScanMission.ClientReadInitial: item count does not match the server count ({itemCount} != {startingItems.Count}, mission: {Prefab.Identifier})");
|
||||||
|
}
|
||||||
|
scanners.Clear();
|
||||||
|
GetScanners();
|
||||||
|
ClientReadScanTargetStatus(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ClientRead(IReadMessage msg)
|
||||||
|
{
|
||||||
|
base.ClientRead(msg);
|
||||||
|
ClientReadScanTargetStatus(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClientReadScanTargetStatus(IReadMessage msg)
|
||||||
|
{
|
||||||
|
scanTargets.Clear();
|
||||||
|
byte targetsToScan = msg.ReadByte();
|
||||||
|
for (int i = 0; i < targetsToScan; i++)
|
||||||
|
{
|
||||||
|
ushort id = msg.ReadUInt16();
|
||||||
|
bool scanned = msg.ReadBoolean();
|
||||||
|
Entity entity = Entity.FindEntityByID(id);
|
||||||
|
scanTargets.Add(entity as WayPoint, scanned);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -130,6 +130,7 @@ namespace Barotrauma
|
|||||||
public static GUIStyle Style;
|
public static GUIStyle Style;
|
||||||
|
|
||||||
private static Texture2D t;
|
private static Texture2D t;
|
||||||
|
public static Texture2D WhiteTexture => t;
|
||||||
private static Sprite[] MouseCursorSprites => Style.CursorSprite;
|
private static Sprite[] MouseCursorSprites => Style.CursorSprite;
|
||||||
|
|
||||||
private static bool debugDrawSounds, debugDrawEvents, debugDrawMetadata;
|
private static bool debugDrawSounds, debugDrawEvents, debugDrawMetadata;
|
||||||
@@ -163,6 +164,7 @@ namespace Barotrauma
|
|||||||
public static ScalableFont SubHeadingFont => Style?.SubHeadingFont;
|
public static ScalableFont SubHeadingFont => Style?.SubHeadingFont;
|
||||||
public static ScalableFont DigitalFont => Style?.DigitalFont;
|
public static ScalableFont DigitalFont => Style?.DigitalFont;
|
||||||
public static ScalableFont HotkeyFont => Style?.HotkeyFont;
|
public static ScalableFont HotkeyFont => Style?.HotkeyFont;
|
||||||
|
public static ScalableFont MonospacedFont => Style?.MonospacedFont;
|
||||||
|
|
||||||
public static ScalableFont CJKFont { get; private set; }
|
public static ScalableFont CJKFont { get; private set; }
|
||||||
|
|
||||||
@@ -306,7 +308,7 @@ namespace Barotrauma
|
|||||||
});
|
});
|
||||||
|
|
||||||
SubmarineIcon = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(452, 385, 182, 81), new Vector2(0.5f, 0.5f));
|
SubmarineIcon = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(452, 385, 182, 81), new Vector2(0.5f, 0.5f));
|
||||||
arrow = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(392, 393, 49, 45), new Vector2(0.5f, 0.5f));
|
arrow = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(393, 393, 49, 45), new Vector2(0.5f, 0.5f));
|
||||||
SpeechBubbleIcon = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(385, 449, 66, 60), new Vector2(0.5f, 0.5f));
|
SpeechBubbleIcon = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(385, 449, 66, 60), new Vector2(0.5f, 0.5f));
|
||||||
BrokenIcon = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(898, 386, 123, 123), new Vector2(0.5f, 0.5f));
|
BrokenIcon = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(898, 386, 123, 123), new Vector2(0.5f, 0.5f));
|
||||||
}
|
}
|
||||||
@@ -672,6 +674,12 @@ namespace Barotrauma
|
|||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: SamplerStateClamp, rasterizerState: GameMain.ScissorTestEnable);
|
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: SamplerStateClamp, rasterizerState: GameMain.ScissorTestEnable);
|
||||||
|
|
||||||
|
if (GameMain.GameSession?.CrewManager is { DraggedOrder: { SymbolSprite: { } orderSprite, Color: var color }, DragOrder: true })
|
||||||
|
{
|
||||||
|
float spriteSize = Math.Max(orderSprite.size.X, orderSprite.size.Y);
|
||||||
|
orderSprite.Draw(spriteBatch, PlayerInput.LatestMousePosition, color, orderSprite.size / 2f, scale: 32f / spriteSize * Scale);
|
||||||
|
}
|
||||||
|
|
||||||
var sprite = MouseCursorSprites[(int)MouseCursor] ?? MouseCursorSprites[(int)CursorState.Default];
|
var sprite = MouseCursorSprites[(int)MouseCursor] ?? MouseCursorSprites[(int)CursorState.Default];
|
||||||
sprite.Draw(spriteBatch, PlayerInput.LatestMousePosition, Color.White, sprite.Origin, 0f, Scale / 1.5f);
|
sprite.Draw(spriteBatch, PlayerInput.LatestMousePosition, Color.White, sprite.Origin, 0f, Scale / 1.5f);
|
||||||
|
|
||||||
@@ -855,11 +863,10 @@ namespace Barotrauma
|
|||||||
int index = 0;
|
int index = 0;
|
||||||
if (updateList.Count > 0)
|
if (updateList.Count > 0)
|
||||||
{
|
{
|
||||||
index = updateList.Count - 1;
|
index = updateList.Count;
|
||||||
while (updateList[index].UpdateOrder > item.UpdateOrder)
|
while (index > 0 && updateList[index-1].UpdateOrder > item.UpdateOrder)
|
||||||
{
|
{
|
||||||
index--;
|
index--;
|
||||||
if (index == 0) { break; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!updateListSet.Contains(item))
|
if (!updateListSet.Contains(item))
|
||||||
@@ -928,12 +935,13 @@ namespace Barotrauma
|
|||||||
MouseOn = null;
|
MouseOn = null;
|
||||||
int inventoryIndex = -1;
|
int inventoryIndex = -1;
|
||||||
|
|
||||||
if (Inventory.IsMouseOnInventory())
|
Inventory.RefreshMouseOnInventory();
|
||||||
|
if (Inventory.IsMouseOnInventory)
|
||||||
{
|
{
|
||||||
inventoryIndex = updateList.IndexOf(CharacterHUD.HUDFrame);
|
inventoryIndex = updateList.IndexOf(CharacterHUD.HUDFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PlayerInput.PrimaryMouseButtonHeld() && !PlayerInput.PrimaryMouseButtonClicked())
|
if ((!PlayerInput.PrimaryMouseButtonHeld() && !PlayerInput.PrimaryMouseButtonClicked()) || (prevMouseOn == null && !PlayerInput.SecondaryMouseButtonHeld()))
|
||||||
{
|
{
|
||||||
for (var i = updateList.Count - 1; i > inventoryIndex; i--)
|
for (var i = updateList.Count - 1; i > inventoryIndex; i--)
|
||||||
{
|
{
|
||||||
@@ -941,10 +949,9 @@ namespace Barotrauma
|
|||||||
if (!c.CanBeFocused) { continue; }
|
if (!c.CanBeFocused) { continue; }
|
||||||
if (c.MouseRect.Contains(PlayerInput.MousePosition))
|
if (c.MouseRect.Contains(PlayerInput.MousePosition))
|
||||||
{
|
{
|
||||||
if ((!PlayerInput.PrimaryMouseButtonHeld() && !PlayerInput.PrimaryMouseButtonClicked()) || c == prevMouseOn)
|
if ((!PlayerInput.PrimaryMouseButtonHeld() && !PlayerInput.PrimaryMouseButtonClicked()) || c == prevMouseOn || prevMouseOn == null)
|
||||||
{
|
{
|
||||||
MouseOn = c;
|
MouseOn = c;
|
||||||
var sakdjfnsjkd = c.MouseRect;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -958,7 +965,6 @@ namespace Barotrauma
|
|||||||
MouseCursor = UpdateMouseCursorState(MouseOn);
|
MouseCursor = UpdateMouseCursorState(MouseOn);
|
||||||
return MouseOn;
|
return MouseOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CursorState UpdateMouseCursorState(GUIComponent c)
|
private static CursorState UpdateMouseCursorState(GUIComponent c)
|
||||||
@@ -1051,12 +1057,15 @@ namespace Barotrauma
|
|||||||
if (listBox.DraggedElement != null) { return CursorState.Dragging; }
|
if (listBox.DraggedElement != null) { return CursorState.Dragging; }
|
||||||
if (listBox.CanDragElements) { return CursorState.Move; }
|
if (listBox.CanDragElements) { return CursorState.Move; }
|
||||||
|
|
||||||
var hoverParent = c;
|
if (listBox.HoverCursor != CursorState.Default)
|
||||||
while (true)
|
|
||||||
{
|
{
|
||||||
if (hoverParent == parent || hoverParent == null) { break; }
|
var hoverParent = c;
|
||||||
if (hoverParent.State == GUIComponent.ComponentState.Hover) { return CursorState.Hand; }
|
while (true)
|
||||||
hoverParent = hoverParent.Parent;
|
{
|
||||||
|
if (hoverParent == parent || hoverParent == null) { break; }
|
||||||
|
if (hoverParent.State == GUIComponent.ComponentState.Hover) { return CursorState.Hand; }
|
||||||
|
hoverParent = hoverParent.Parent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1066,7 +1075,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Inventory.IsMouseOnInventory()) { return Inventory.GetInventoryMouseCursor(); }
|
if (Inventory.IsMouseOnInventory) { return Inventory.GetInventoryMouseCursor(); }
|
||||||
|
|
||||||
var character = Character.Controlled;
|
var character = Character.Controlled;
|
||||||
// ReSharper disable once InvertIf
|
// ReSharper disable once InvertIf
|
||||||
@@ -1343,7 +1352,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
/// <param name="createOffset">Should the indicator move based on the camera position?</param>
|
/// <param name="createOffset">Should the indicator move based on the camera position?</param>
|
||||||
/// <param name="overrideAlpha">Override the distance-based alpha value with the specified alpha value</param>
|
/// <param name="overrideAlpha">Override the distance-based alpha value with the specified alpha value</param>
|
||||||
public static void DrawIndicator(SpriteBatch spriteBatch, in Vector2 worldPosition, Camera cam, in Vector2 visibleRange, Sprite sprite, in Color color,
|
public static void DrawIndicator(SpriteBatch spriteBatch, in Vector2 worldPosition, Camera cam, in Range<float> visibleRange, Sprite sprite, in Color color,
|
||||||
bool createOffset = true, float scaleMultiplier = 1.0f, float? overrideAlpha = null)
|
bool createOffset = true, float scaleMultiplier = 1.0f, float? overrideAlpha = null)
|
||||||
{
|
{
|
||||||
Vector2 diff = worldPosition - cam.WorldViewCenter;
|
Vector2 diff = worldPosition - cam.WorldViewCenter;
|
||||||
@@ -1351,9 +1360,9 @@ namespace Barotrauma
|
|||||||
|
|
||||||
float symbolScale = Math.Min(64.0f / sprite.size.X, 1.0f) * scaleMultiplier * Scale;
|
float symbolScale = Math.Min(64.0f / sprite.size.X, 1.0f) * scaleMultiplier * Scale;
|
||||||
|
|
||||||
if (overrideAlpha.HasValue || (dist > visibleRange.X && dist < visibleRange.Y))
|
if (overrideAlpha.HasValue || (dist > visibleRange.Start && dist < visibleRange.End))
|
||||||
{
|
{
|
||||||
float alpha = overrideAlpha ?? MathUtils.Min((dist - visibleRange.X) / 100.0f, 1.0f - ((dist - visibleRange.Y + 100f) / 100.0f), 1.0f);
|
float alpha = overrideAlpha ?? MathUtils.Min((dist - visibleRange.Start) / 100.0f, 1.0f - ((dist - visibleRange.End + 100f) / 100.0f), 1.0f);
|
||||||
Vector2 targetScreenPos = cam.WorldToScreen(worldPosition);
|
Vector2 targetScreenPos = cam.WorldToScreen(worldPosition);
|
||||||
|
|
||||||
if (!createOffset)
|
if (!createOffset)
|
||||||
@@ -1417,7 +1426,7 @@ namespace Barotrauma
|
|||||||
public static void DrawIndicator(SpriteBatch spriteBatch, Vector2 worldPosition, Camera cam, float hideDist, Sprite sprite, Color color,
|
public static void DrawIndicator(SpriteBatch spriteBatch, Vector2 worldPosition, Camera cam, float hideDist, Sprite sprite, Color color,
|
||||||
bool createOffset = true, float scaleMultiplier = 1.0f, float? overrideAlpha = null)
|
bool createOffset = true, float scaleMultiplier = 1.0f, float? overrideAlpha = null)
|
||||||
{
|
{
|
||||||
DrawIndicator(spriteBatch, worldPosition, cam, new Vector2(hideDist, float.PositiveInfinity), sprite, color, createOffset, scaleMultiplier, overrideAlpha);
|
DrawIndicator(spriteBatch, worldPosition, cam, new Range<float>(hideDist, float.PositiveInfinity), sprite, color, createOffset, scaleMultiplier, overrideAlpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DrawLine(SpriteBatch sb, Vector2 start, Vector2 end, Color clr, float depth = 0.0f, float width = 1)
|
public static void DrawLine(SpriteBatch sb, Vector2 start, Vector2 end, Color clr, float depth = 0.0f, float width = 1)
|
||||||
@@ -1520,6 +1529,11 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void DrawFilledRectangle(SpriteBatch sb, RectangleF rect, Color clr, float depth = 0.0f)
|
||||||
|
{
|
||||||
|
DrawFilledRectangle(sb, rect.Location, rect.Size, clr, depth);
|
||||||
|
}
|
||||||
|
|
||||||
public static void DrawFilledRectangle(SpriteBatch sb, Vector2 start, Vector2 size, Color clr, float depth = 0.0f)
|
public static void DrawFilledRectangle(SpriteBatch sb, Vector2 start, Vector2 size, Color clr, float depth = 0.0f)
|
||||||
{
|
{
|
||||||
if (size.X < 0)
|
if (size.X < 0)
|
||||||
@@ -2433,14 +2447,43 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (messages.Any(msg => msg.Text == message)) { return; }
|
if (messages.Any(msg => msg.Text == message)) { return; }
|
||||||
messages.Add(new GUIMessage(message, color, lifeTime ?? MathHelper.Clamp(message.Length / 5.0f, 3.0f, 10.0f), font ?? LargeFont));
|
messages.Add(new GUIMessage(message, color, lifeTime ?? MathHelper.Clamp(message.Length / 5.0f, 3.0f, 10.0f), font ?? LargeFont));
|
||||||
if (playSound) SoundPlayer.PlayUISound(GUISoundType.UIMessage);
|
if (playSound) { SoundPlayer.PlayUISound(GUISoundType.UIMessage); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AddMessage(string message, Color color, Vector2 pos, Vector2 velocity, float lifeTime = 3.0f, bool playSound = true, GUISoundType soundType = GUISoundType.UIMessage, int subId = -1)
|
public static void AddMessage(string message, Color color, Vector2 pos, Vector2 velocity, float lifeTime = 3.0f, bool playSound = true, GUISoundType soundType = GUISoundType.UIMessage, int subId = -1)
|
||||||
{
|
{
|
||||||
Submarine sub = Submarine.Loaded.FirstOrDefault(s => s.ID == subId);
|
Submarine sub = Submarine.Loaded.FirstOrDefault(s => s.ID == subId);
|
||||||
messages.Add(new GUIMessage(message, color, pos, velocity, lifeTime, Alignment.Center, LargeFont, sub: sub));
|
|
||||||
if (playSound) SoundPlayer.PlayUISound(soundType);
|
var newMessage = new GUIMessage(message, color, pos, velocity, lifeTime, Alignment.Center, Font, sub: sub);
|
||||||
|
if (playSound) { SoundPlayer.PlayUISound(soundType); }
|
||||||
|
bool overlapFound = true;
|
||||||
|
int tries = 0;
|
||||||
|
while (overlapFound)
|
||||||
|
{
|
||||||
|
overlapFound = false;
|
||||||
|
foreach (var otherMessage in messages)
|
||||||
|
{
|
||||||
|
float xDiff = otherMessage.Pos.X - newMessage.Pos.X;
|
||||||
|
if (Math.Abs(xDiff) > (newMessage.Size.X + otherMessage.Size.X) / 2) { continue; }
|
||||||
|
float yDiff = otherMessage.Pos.Y - newMessage.Pos.Y;
|
||||||
|
if (Math.Abs(yDiff) > (newMessage.Size.Y + otherMessage.Size.Y) / 2) { continue; }
|
||||||
|
Vector2 moveDir = -(new Vector2(xDiff, yDiff) + Rand.Vector(1.0f));
|
||||||
|
if (moveDir.LengthSquared() > 0.0001f)
|
||||||
|
{
|
||||||
|
moveDir = Vector2.Normalize(moveDir);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
moveDir = Rand.Vector(1.0f);
|
||||||
|
}
|
||||||
|
moveDir.Y = -Math.Abs(moveDir.Y);
|
||||||
|
newMessage.Pos -= Vector2.UnitY * 10;
|
||||||
|
}
|
||||||
|
tries++;
|
||||||
|
if (tries > 20) { break; }
|
||||||
|
}
|
||||||
|
|
||||||
|
messages.Add(newMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ClearMessages()
|
public static void ClearMessages()
|
||||||
|
|||||||
@@ -52,13 +52,13 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public GUIComponent GetChild(int index)
|
public GUIComponent GetChild(int index)
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= CountChildren) return null;
|
if (index < 0 || index >= CountChildren) { return null; }
|
||||||
return RectTransform.GetChild(index).GUIComponent;
|
return RectTransform.GetChild(index).GUIComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetChildIndex(GUIComponent child)
|
public int GetChildIndex(GUIComponent child)
|
||||||
{
|
{
|
||||||
if (child == null) return -1;
|
if (child == null) { return -1; }
|
||||||
return RectTransform.GetChildIndex(child.RectTransform);
|
return RectTransform.GetChildIndex(child.RectTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
foreach (GUIComponent child in Children)
|
foreach (GUIComponent child in Children)
|
||||||
{
|
{
|
||||||
if (child.UserData == obj || (child.userData != null && child.userData.Equals(obj))) return child;
|
if (child.UserData == obj || (child.userData != null && child.userData.Equals(obj))) { return child; }
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -175,6 +175,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public bool GlowOnSelect { get; set; }
|
public bool GlowOnSelect { get; set; }
|
||||||
|
|
||||||
|
public Vector2 UVOffset { get; set; }
|
||||||
|
|
||||||
private CoroutineHandle pulsateCoroutine;
|
private CoroutineHandle pulsateCoroutine;
|
||||||
|
|
||||||
protected Color flashColor;
|
protected Color flashColor;
|
||||||
@@ -256,9 +258,9 @@ namespace Barotrauma
|
|||||||
|
|
||||||
protected Rectangle ClampRect(Rectangle r)
|
protected Rectangle ClampRect(Rectangle r)
|
||||||
{
|
{
|
||||||
if (Parent == null || !ClampMouseRectToParent) return r;
|
if (Parent == null || !ClampMouseRectToParent) { return r; }
|
||||||
Rectangle parentRect = Parent.ClampRect(Parent.Rect);
|
Rectangle parentRect = Parent.ClampRect(Parent.Rect);
|
||||||
if (parentRect.Width <= 0 || parentRect.Height <= 0) return Rectangle.Empty;
|
if (parentRect.Width <= 0 || parentRect.Height <= 0) { return Rectangle.Empty; }
|
||||||
if (parentRect.X > r.X)
|
if (parentRect.X > r.X)
|
||||||
{
|
{
|
||||||
int diff = parentRect.X - r.X;
|
int diff = parentRect.X - r.X;
|
||||||
@@ -281,7 +283,7 @@ namespace Barotrauma
|
|||||||
int diff = (r.Y + r.Height) - (parentRect.Y + parentRect.Height);
|
int diff = (r.Y + r.Height) - (parentRect.Y + parentRect.Height);
|
||||||
r.Height -= diff;
|
r.Height -= diff;
|
||||||
}
|
}
|
||||||
if (r.Width <= 0 || r.Height <= 0) return Rectangle.Empty;
|
if (r.Width <= 0 || r.Height <= 0) { return Rectangle.Empty; }
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,7 +297,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (!CanBeFocused) return Rectangle.Empty;
|
if (!CanBeFocused) { return Rectangle.Empty; }
|
||||||
return ClampMouseRectToParent ? ClampRect(Rect) : Rect;
|
return ClampMouseRectToParent ? ClampRect(Rect) : Rect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -431,7 +433,7 @@ namespace Barotrauma
|
|||||||
#region Updating
|
#region Updating
|
||||||
public virtual void AddToGUIUpdateList(bool ignoreChildren = false, int order = 0)
|
public virtual void AddToGUIUpdateList(bool ignoreChildren = false, int order = 0)
|
||||||
{
|
{
|
||||||
if (!Visible) return;
|
if (!Visible) { return; }
|
||||||
|
|
||||||
UpdateOrder = order;
|
UpdateOrder = order;
|
||||||
GUI.AddToUpdateList(this);
|
GUI.AddToUpdateList(this);
|
||||||
@@ -463,7 +465,7 @@ namespace Barotrauma
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void UpdateManually(float deltaTime, bool alsoChildren = false, bool recursive = true)
|
public void UpdateManually(float deltaTime, bool alsoChildren = false, bool recursive = true)
|
||||||
{
|
{
|
||||||
if (!Visible) return;
|
if (!Visible) { return; }
|
||||||
|
|
||||||
AutoUpdate = false;
|
AutoUpdate = false;
|
||||||
Update(deltaTime);
|
Update(deltaTime);
|
||||||
@@ -475,7 +477,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
protected virtual void Update(float deltaTime)
|
protected virtual void Update(float deltaTime)
|
||||||
{
|
{
|
||||||
if (!Visible) return;
|
if (!Visible) { return; }
|
||||||
|
|
||||||
if (CanBeFocused && OnSecondaryClicked != null)
|
if (CanBeFocused && OnSecondaryClicked != null)
|
||||||
{
|
{
|
||||||
@@ -555,7 +557,7 @@ namespace Barotrauma
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual void DrawManually(SpriteBatch spriteBatch, bool alsoChildren = false, bool recursive = true)
|
public virtual void DrawManually(SpriteBatch spriteBatch, bool alsoChildren = false, bool recursive = true)
|
||||||
{
|
{
|
||||||
if (!Visible) return;
|
if (!Visible) { return; }
|
||||||
|
|
||||||
AutoDraw = false;
|
AutoDraw = false;
|
||||||
Draw(spriteBatch);
|
Draw(spriteBatch);
|
||||||
@@ -598,7 +600,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
protected virtual void Draw(SpriteBatch spriteBatch)
|
protected virtual void Draw(SpriteBatch spriteBatch)
|
||||||
{
|
{
|
||||||
if (!Visible) return;
|
if (!Visible) { return; }
|
||||||
var rect = Rect;
|
var rect = Rect;
|
||||||
|
|
||||||
GetBlendedColor(GetColor(State), ref _currentColor);
|
GetBlendedColor(GetColor(State), ref _currentColor);
|
||||||
@@ -653,7 +655,7 @@ namespace Barotrauma
|
|||||||
? MathUtils.InverseLerp(0, SpriteCrossFadeTime, ToolBox.GetEasing(uiSprite.TransitionMode, spriteFadeTimer)) : 0;
|
? MathUtils.InverseLerp(0, SpriteCrossFadeTime, ToolBox.GetEasing(uiSprite.TransitionMode, spriteFadeTimer)) : 0;
|
||||||
if (alphaMultiplier > 0)
|
if (alphaMultiplier > 0)
|
||||||
{
|
{
|
||||||
uiSprite.Draw(spriteBatch, rect, previousColor * alphaMultiplier, SpriteEffects);
|
uiSprite.Draw(spriteBatch, rect, previousColor * alphaMultiplier, SpriteEffects, uvOffset: UVOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -667,7 +669,11 @@ namespace Barotrauma
|
|||||||
? MathUtils.InverseLerp(SpriteCrossFadeTime, 0, ToolBox.GetEasing(uiSprite.TransitionMode, spriteFadeTimer)) : (_currentColor.A / 255.0f);
|
? MathUtils.InverseLerp(SpriteCrossFadeTime, 0, ToolBox.GetEasing(uiSprite.TransitionMode, spriteFadeTimer)) : (_currentColor.A / 255.0f);
|
||||||
if (alphaMultiplier > 0)
|
if (alphaMultiplier > 0)
|
||||||
{
|
{
|
||||||
uiSprite.Draw(spriteBatch, rect, _currentColor * alphaMultiplier, SpriteEffects);
|
// * (rect.Location.Y - PlayerInput.MousePosition.Y) / rect.Height
|
||||||
|
Vector2 offset = new Vector2(
|
||||||
|
MathUtils.PositiveModulo((int)-UVOffset.X, uiSprite.Sprite.SourceRect.Width),
|
||||||
|
MathUtils.PositiveModulo((int)-UVOffset.Y, uiSprite.Sprite.SourceRect.Height));
|
||||||
|
uiSprite.Draw(spriteBatch, rect, _currentColor * alphaMultiplier, SpriteEffects, uvOffset: offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -708,7 +714,7 @@ namespace Barotrauma
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void DrawToolTip(SpriteBatch spriteBatch)
|
public void DrawToolTip(SpriteBatch spriteBatch)
|
||||||
{
|
{
|
||||||
if (!Visible) return;
|
if (!Visible) { return; }
|
||||||
DrawToolTip(spriteBatch, ToolTip, GUI.MouseOn.Rect, TooltipRichTextData);
|
DrawToolTip(spriteBatch, ToolTip, GUI.MouseOn.Rect, TooltipRichTextData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1048,7 +1054,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
case "language":
|
case "language":
|
||||||
string[] languages = element.GetAttributeStringArray(attribute.Name.ToString(), new string[0]);
|
string[] languages = element.GetAttributeStringArray(attribute.Name.ToString(), new string[0]);
|
||||||
if (!languages.Any(l => GameMain.Config.Language.ToLower() == l.ToLower())) { return false; }
|
if (!languages.Any(l => GameMain.Config.Language.Equals(l, StringComparison.OrdinalIgnoreCase))) { return false; }
|
||||||
break;
|
break;
|
||||||
case "gameversion":
|
case "gameversion":
|
||||||
var version = new Version(attribute.Value);
|
var version = new Version(attribute.Value);
|
||||||
@@ -1213,8 +1219,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private static GUIImage LoadGUIImage(XElement element, RectTransform parent)
|
private static GUIImage LoadGUIImage(XElement element, RectTransform parent)
|
||||||
{
|
{
|
||||||
Sprite sprite = null;
|
Sprite sprite;
|
||||||
|
|
||||||
string url = element.GetAttributeString("url", "");
|
string url = element.GetAttributeString("url", "");
|
||||||
if (!string.IsNullOrEmpty(url))
|
if (!string.IsNullOrEmpty(url))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public bool Dropped { get; set; }
|
public bool Dropped { get; set; }
|
||||||
|
|
||||||
|
public bool AllowNonText { get; set; }
|
||||||
|
|
||||||
public object SelectedItemData
|
public object SelectedItemData
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -318,9 +320,9 @@ namespace Barotrauma
|
|||||||
if (textBlock == null)
|
if (textBlock == null)
|
||||||
{
|
{
|
||||||
textBlock = component.GetChild<GUITextBlock>();
|
textBlock = component.GetChild<GUITextBlock>();
|
||||||
if (textBlock == null) return false;
|
if (textBlock is null && !AllowNonText) { return false; }
|
||||||
}
|
}
|
||||||
button.Text = textBlock.Text;
|
button.Text = textBlock?.Text ?? "";
|
||||||
}
|
}
|
||||||
Dropped = false;
|
Dropped = false;
|
||||||
// TODO: OnSelected can be called multiple times and when it shouldn't be called -> turn into an event so that nobody else can call it.
|
// TODO: OnSelected can be called multiple times and when it shouldn't be called -> turn into an event so that nobody else can call it.
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
public class GUIFrame : GUIComponent
|
public class GUIFrame : GUIComponent
|
||||||
{
|
{
|
||||||
public int OutlineThickness { get; set; }
|
public float OutlineThickness { get; set; }
|
||||||
|
|
||||||
public GUIFrame(RectTransform rectT, string style = "", Color? color = null) : base(style, rectT)
|
public GUIFrame(RectTransform rectT, string style = "", Color? color = null) : base(style, rectT)
|
||||||
{
|
{
|
||||||
@@ -28,7 +28,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (OutlineColor != Color.Transparent)
|
if (OutlineColor != Color.Transparent)
|
||||||
{
|
{
|
||||||
GUI.DrawRectangle(spriteBatch, Rect, OutlineColor * (OutlineColor.A/255.0f), false, thickness: OutlineThickness);
|
GUI.DrawRectangle(spriteBatch, Rect, OutlineColor, false, thickness: OutlineThickness);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ namespace Barotrauma
|
|||||||
if (BlendState != null)
|
if (BlendState != null)
|
||||||
{
|
{
|
||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
spriteBatch.Begin(blendState: BlendState, samplerState: GUI.SamplerState);
|
spriteBatch.Begin(blendState: BlendState, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (style != null)
|
if (style != null)
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ namespace Barotrauma
|
|||||||
public GUIFrame Content { get; private set; }
|
public GUIFrame Content { get; private set; }
|
||||||
public GUIScrollBar ScrollBar { get; private set; }
|
public GUIScrollBar ScrollBar { get; private set; }
|
||||||
|
|
||||||
private Dictionary<GUIComponent, bool> childVisible = new Dictionary<GUIComponent, bool>();
|
private readonly Dictionary<GUIComponent, bool> childVisible = new Dictionary<GUIComponent, bool>();
|
||||||
|
|
||||||
private int totalSize;
|
private int totalSize;
|
||||||
private bool childrenNeedsRecalculation;
|
private bool childrenNeedsRecalculation;
|
||||||
@@ -224,7 +224,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (value == false && canDragElements && draggedElement != null)
|
if (value == false && canDragElements && draggedElement != null)
|
||||||
{
|
{
|
||||||
draggedElement = null;
|
DraggedElement = null;
|
||||||
}
|
}
|
||||||
canDragElements = value;
|
canDragElements = value;
|
||||||
}
|
}
|
||||||
@@ -233,11 +233,29 @@ namespace Barotrauma
|
|||||||
private GUIComponent draggedElement;
|
private GUIComponent draggedElement;
|
||||||
private Rectangle draggedReferenceRectangle;
|
private Rectangle draggedReferenceRectangle;
|
||||||
private Point draggedReferenceOffset;
|
private Point draggedReferenceOffset;
|
||||||
|
public bool HasDraggedElementIndexChanged { get; private set; }
|
||||||
|
|
||||||
public GUIComponent DraggedElement => draggedElement;
|
public GUIComponent DraggedElement
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return draggedElement;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == draggedElement) { return; }
|
||||||
|
draggedElement = value;
|
||||||
|
HasDraggedElementIndexChanged = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private readonly bool isHorizontal;
|
private readonly bool isHorizontal;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Setting this to true and CanBeFocused to false allows the list background to be unfocusable while the elements can still be interacted with.
|
||||||
|
/// </summary>
|
||||||
|
public bool CanInteractWhenUnfocusable { get; set; } = false;
|
||||||
|
|
||||||
/// <param name="isScrollBarOnDefaultSide">For horizontal listbox, default side is on the bottom. For vertical, it's on the right.</param>
|
/// <param name="isScrollBarOnDefaultSide">For horizontal listbox, default side is on the bottom. For vertical, it's on the right.</param>
|
||||||
public GUIListBox(RectTransform rectT, bool isHorizontal = false, Color? color = null, string style = "", bool isScrollBarOnDefaultSide = true, bool useMouseDownToSelect = false) : base(style, rectT)
|
public GUIListBox(RectTransform rectT, bool isHorizontal = false, Color? color = null, string style = "", bool isScrollBarOnDefaultSide = true, bool useMouseDownToSelect = false) : base(style, rectT)
|
||||||
{
|
{
|
||||||
@@ -472,7 +490,7 @@ namespace Barotrauma
|
|||||||
if (!PlayerInput.PrimaryMouseButtonHeld())
|
if (!PlayerInput.PrimaryMouseButtonHeld())
|
||||||
{
|
{
|
||||||
OnRearranged?.Invoke(this, draggedElement.UserData);
|
OnRearranged?.Invoke(this, draggedElement.UserData);
|
||||||
draggedElement = null;
|
DraggedElement = null;
|
||||||
RepositionChildren();
|
RepositionChildren();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -518,6 +536,7 @@ namespace Barotrauma
|
|||||||
if (currIndex != index)
|
if (currIndex != index)
|
||||||
{
|
{
|
||||||
draggedElement.RectTransform.RepositionChildInHierarchy(currIndex);
|
draggedElement.RectTransform.RepositionChildInHierarchy(currIndex);
|
||||||
|
HasDraggedElementIndexChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -556,7 +575,7 @@ namespace Barotrauma
|
|||||||
if (child == null || !child.Visible) { continue; }
|
if (child == null || !child.Visible) { continue; }
|
||||||
|
|
||||||
// selecting
|
// selecting
|
||||||
if (Enabled && CanBeFocused && child.CanBeFocused && child.Rect.Contains(PlayerInput.MousePosition) && GUI.IsMouseOn(child))
|
if (Enabled && (CanBeFocused || CanInteractWhenUnfocusable) && child.CanBeFocused && child.Rect.Contains(PlayerInput.MousePosition) && GUI.IsMouseOn(child))
|
||||||
{
|
{
|
||||||
child.State = ComponentState.Hover;
|
child.State = ComponentState.Hover;
|
||||||
|
|
||||||
@@ -577,7 +596,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (CanDragElements && PlayerInput.PrimaryMouseButtonDown() && GUI.MouseOn == child)
|
if (CanDragElements && PlayerInput.PrimaryMouseButtonDown() && GUI.MouseOn == child)
|
||||||
{
|
{
|
||||||
draggedElement = child;
|
DraggedElement = child;
|
||||||
draggedReferenceRectangle = child.Rect;
|
draggedReferenceRectangle = child.Rect;
|
||||||
draggedReferenceOffset = child.RectTransform.AbsoluteOffset;
|
draggedReferenceOffset = child.RectTransform.AbsoluteOffset;
|
||||||
}
|
}
|
||||||
@@ -681,6 +700,8 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ForceUpdate() => Update((float)Timing.Step);
|
||||||
|
|
||||||
protected override void Update(float deltaTime)
|
protected override void Update(float deltaTime)
|
||||||
{
|
{
|
||||||
if (!Visible) { return; }
|
if (!Visible) { return; }
|
||||||
@@ -750,7 +771,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((GUI.IsMouseOn(this) || GUI.IsMouseOn(ScrollBar)) && AllowMouseWheelScroll && PlayerInput.ScrollWheelSpeed != 0)
|
if (PlayerInput.ScrollWheelSpeed != 0 && AllowMouseWheelScroll && (FindScrollableParentListBox(GUI.MouseOn) == this || GUI.IsMouseOn(ScrollBar)))
|
||||||
{
|
{
|
||||||
if (SmoothScroll)
|
if (SmoothScroll)
|
||||||
{
|
{
|
||||||
@@ -774,7 +795,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ScrollBar.Enabled = ScrollBarEnabled && BarSize < 1.0f;
|
ScrollBar.Enabled = ScrollBarEnabled && BarSize < 1.0f;
|
||||||
if (AutoHideScrollBar)
|
if (AutoHideScrollBar)
|
||||||
{
|
{
|
||||||
@@ -786,6 +806,13 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static GUIListBox FindScrollableParentListBox(GUIComponent target)
|
||||||
|
{
|
||||||
|
if (target is GUIListBox listBox && listBox.ScrollBarEnabled && listBox.BarSize < 1.0f) { return listBox; }
|
||||||
|
if (target?.Parent == null) { return null; }
|
||||||
|
return FindScrollableParentListBox(target.Parent);
|
||||||
|
}
|
||||||
|
|
||||||
public void SelectNext(bool force = false, bool autoScroll = true, bool takeKeyBoardFocus = false)
|
public void SelectNext(bool force = false, bool autoScroll = true, bool takeKeyBoardFocus = false)
|
||||||
{
|
{
|
||||||
int index = SelectedIndex + 1;
|
int index = SelectedIndex + 1;
|
||||||
@@ -982,7 +1009,7 @@ namespace Barotrauma
|
|||||||
if (child == null) { return; }
|
if (child == null) { return; }
|
||||||
child.RectTransform.Parent = null;
|
child.RectTransform.Parent = null;
|
||||||
if (selected.Contains(child)) { selected.Remove(child); }
|
if (selected.Contains(child)) { selected.Remove(child); }
|
||||||
if (draggedElement == child) { draggedElement = null; }
|
if (draggedElement == child) { DraggedElement = null; }
|
||||||
UpdateScrollBarSize();
|
UpdateScrollBarSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -999,7 +1026,6 @@ namespace Barotrauma
|
|||||||
ContentBackground.DrawManually(spriteBatch, alsoChildren: false);
|
ContentBackground.DrawManually(spriteBatch, alsoChildren: false);
|
||||||
|
|
||||||
Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle;
|
Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle;
|
||||||
RasterizerState prevRasterizerState = spriteBatch.GraphicsDevice.RasterizerState;
|
|
||||||
if (HideChildrenOutsideFrame)
|
if (HideChildrenOutsideFrame)
|
||||||
{
|
{
|
||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
@@ -1027,7 +1053,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
spriteBatch.GraphicsDevice.ScissorRectangle = prevScissorRect;
|
spriteBatch.GraphicsDevice.ScissorRectangle = prevScissorRect;
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: prevRasterizerState);
|
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ScrollBarVisible)
|
if (ScrollBarVisible)
|
||||||
|
|||||||
@@ -79,14 +79,14 @@ namespace Barotrauma
|
|||||||
new Rectangle(
|
new Rectangle(
|
||||||
sliderArea.X + (int)sliceBorderSizes.X,
|
sliderArea.X + (int)sliceBorderSizes.X,
|
||||||
sliderArea.Y,
|
sliderArea.Y,
|
||||||
(int)((sliderArea.Width - sliceBorderSizes.X - sliceBorderSizes.Z) * fillAmount),
|
(int)Math.Round((sliderArea.Width - sliceBorderSizes.X - sliceBorderSizes.Z) * fillAmount),
|
||||||
sliderArea.Height)
|
sliderArea.Height)
|
||||||
:
|
:
|
||||||
new Rectangle(
|
new Rectangle(
|
||||||
sliderArea.X,
|
sliderArea.X,
|
||||||
(int)(sliderArea.Bottom - (sliderArea.Height - sliceBorderSizes.Y - sliceBorderSizes.W) * fillAmount - sliceBorderSizes.W),
|
(int)Math.Round(sliderArea.Bottom - (sliderArea.Height - sliceBorderSizes.Y - sliceBorderSizes.W) * fillAmount - sliceBorderSizes.W),
|
||||||
sliderArea.Width,
|
sliderArea.Width,
|
||||||
(int)((sliderArea.Height - sliceBorderSizes.Y - sliceBorderSizes.W) * fillAmount));
|
(int)Math.Round((sliderArea.Height - sliceBorderSizes.Y - sliceBorderSizes.W) * fillAmount));
|
||||||
|
|
||||||
sliderRect.Width = Math.Max(sliderRect.Width, 1);
|
sliderRect.Width = Math.Max(sliderRect.Width, 1);
|
||||||
sliderRect.Height = Math.Max(sliderRect.Height, 1);
|
sliderRect.Height = Math.Max(sliderRect.Height, 1);
|
||||||
|
|||||||
@@ -0,0 +1,87 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
public class GUIScissorComponent: GUIComponent
|
||||||
|
{
|
||||||
|
public GUIComponent Content;
|
||||||
|
|
||||||
|
public GUIScissorComponent(RectTransform rectT) : base(null, rectT)
|
||||||
|
{
|
||||||
|
Content = new GUIFrame(new RectTransform(Vector2.One, rectT), style: null)
|
||||||
|
{
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update(float deltaTime)
|
||||||
|
{
|
||||||
|
base.Update(deltaTime);
|
||||||
|
|
||||||
|
foreach (GUIComponent child in Children)
|
||||||
|
{
|
||||||
|
if (child == Content) { continue; }
|
||||||
|
throw new InvalidOperationException($"Children were found in {nameof(GUIScissorComponent)}, Add them to {nameof(GUIScissorComponent)}.{nameof(Content)} instead.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ClampChildMouseRects(Content);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Draw(SpriteBatch spriteBatch)
|
||||||
|
{
|
||||||
|
if (!Visible) { return; }
|
||||||
|
|
||||||
|
Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle;
|
||||||
|
RasterizerState prevRasterizerState = spriteBatch.GraphicsDevice.RasterizerState;
|
||||||
|
|
||||||
|
spriteBatch.End();
|
||||||
|
spriteBatch.GraphicsDevice.ScissorRectangle = Rectangle.Intersect(prevScissorRect, Rect);
|
||||||
|
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
|
||||||
|
|
||||||
|
foreach (GUIComponent child in Content.Children)
|
||||||
|
{
|
||||||
|
if (!child.Visible) { continue; }
|
||||||
|
child.DrawManually(spriteBatch, alsoChildren: true, recursive: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
spriteBatch.End();
|
||||||
|
spriteBatch.GraphicsDevice.ScissorRectangle = prevScissorRect;
|
||||||
|
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: prevRasterizerState);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClampChildMouseRects(GUIComponent child)
|
||||||
|
{
|
||||||
|
child.ClampMouseRectToParent = true;
|
||||||
|
|
||||||
|
if (child is GUIListBox) { return; }
|
||||||
|
|
||||||
|
foreach (GUIComponent grandChild in child.Children)
|
||||||
|
{
|
||||||
|
ClampChildMouseRects(grandChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void AddToGUIUpdateList(bool ignoreChildren = false, int order = 0)
|
||||||
|
{
|
||||||
|
if (!Visible) { return; }
|
||||||
|
|
||||||
|
UpdateOrder = order;
|
||||||
|
GUI.AddToUpdateList(this);
|
||||||
|
|
||||||
|
if (ignoreChildren)
|
||||||
|
{
|
||||||
|
OnAddedToGUIUpdateList?.Invoke(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (GUIComponent child in Content.Children)
|
||||||
|
{
|
||||||
|
if (!child.Visible) { continue; }
|
||||||
|
child.AddToGUIUpdateList(false, order);
|
||||||
|
}
|
||||||
|
OnAddedToGUIUpdateList?.Invoke(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
private Dictionary<string, GUIComponentStyle> componentStyles;
|
private Dictionary<string, GUIComponentStyle> componentStyles;
|
||||||
|
|
||||||
private XElement configElement;
|
private readonly XElement configElement;
|
||||||
|
|
||||||
private GraphicsDevice graphicsDevice;
|
private GraphicsDevice graphicsDevice;
|
||||||
|
|
||||||
@@ -25,6 +25,7 @@ namespace Barotrauma
|
|||||||
public ScalableFont SubHeadingFont { get; private set; }
|
public ScalableFont SubHeadingFont { get; private set; }
|
||||||
public ScalableFont DigitalFont { get; private set; }
|
public ScalableFont DigitalFont { get; private set; }
|
||||||
public ScalableFont HotkeyFont { get; private set; }
|
public ScalableFont HotkeyFont { get; private set; }
|
||||||
|
public ScalableFont MonospacedFont { get; private set; }
|
||||||
|
|
||||||
public Dictionary<ScalableFont, bool> ForceFontUpperCase
|
public Dictionary<ScalableFont, bool> ForceFontUpperCase
|
||||||
{
|
{
|
||||||
@@ -40,12 +41,20 @@ namespace Barotrauma
|
|||||||
public SpriteSheet SavingIndicator { get; private set; }
|
public SpriteSheet SavingIndicator { get; private set; }
|
||||||
|
|
||||||
public UISprite UIGlow { get; private set; }
|
public UISprite UIGlow { get; private set; }
|
||||||
|
|
||||||
|
public UISprite PingCircle { get; private set; }
|
||||||
|
|
||||||
public UISprite UIGlowCircular { get; private set; }
|
public UISprite UIGlowCircular { get; private set; }
|
||||||
|
|
||||||
|
public UISprite UIGlowSolidCircular { get; private set; }
|
||||||
|
public UISprite UIThermalGlow { get; private set; }
|
||||||
|
|
||||||
public UISprite ButtonPulse { get; private set; }
|
public UISprite ButtonPulse { get; private set; }
|
||||||
|
|
||||||
public SpriteSheet FocusIndicator { get; private set; }
|
public SpriteSheet FocusIndicator { get; private set; }
|
||||||
|
|
||||||
|
public UISprite IconOverflowIndicator { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// General green color used for elements whose colors are set from code
|
/// General green color used for elements whose colors are set from code
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -82,6 +91,12 @@ namespace Barotrauma
|
|||||||
public Color TextColorDark { get; private set; } = Color.Black * 0.9f;
|
public Color TextColorDark { get; private set; } = Color.Black * 0.9f;
|
||||||
public Color TextColorDim { get; private set; } = Color.White * 0.6f;
|
public Color TextColorDim { get; private set; } = Color.White * 0.6f;
|
||||||
|
|
||||||
|
public Color ItemQualityColorPoor { get; private set; } = Color.DarkRed;
|
||||||
|
public Color ItemQualityColorNormal { get; private set; } = Color.Gray;
|
||||||
|
public Color ItemQualityColorGood { get; private set; } = Color.LightGreen;
|
||||||
|
public Color ItemQualityColorExcellent { get; private set; } = Color.LightBlue;
|
||||||
|
public Color ItemQualityColorMasterwork { get; private set; } = Color.MediumPurple;
|
||||||
|
|
||||||
public Color ColorReputationVeryLow { get; private set; } = Color.Red;
|
public Color ColorReputationVeryLow { get; private set; } = Color.Red;
|
||||||
public Color ColorReputationLow { get; private set; } = Color.Orange;
|
public Color ColorReputationLow { get; private set; } = Color.Orange;
|
||||||
public Color ColorReputationNeutral { get; private set; } = Color.White * 0.8f;
|
public Color ColorReputationNeutral { get; private set; } = Color.White * 0.8f;
|
||||||
@@ -235,6 +250,9 @@ namespace Barotrauma
|
|||||||
case "uiglow":
|
case "uiglow":
|
||||||
UIGlow = new UISprite(subElement);
|
UIGlow = new UISprite(subElement);
|
||||||
break;
|
break;
|
||||||
|
case "pingcircle":
|
||||||
|
PingCircle = new UISprite(subElement);
|
||||||
|
break;
|
||||||
case "radiation":
|
case "radiation":
|
||||||
RadiationSprite = new UISprite(subElement);
|
RadiationSprite = new UISprite(subElement);
|
||||||
break;
|
break;
|
||||||
@@ -244,9 +262,18 @@ namespace Barotrauma
|
|||||||
case "uiglowcircular":
|
case "uiglowcircular":
|
||||||
UIGlowCircular = new UISprite(subElement);
|
UIGlowCircular = new UISprite(subElement);
|
||||||
break;
|
break;
|
||||||
|
case "uiglowsolidcircular":
|
||||||
|
UIGlowSolidCircular = new UISprite(subElement);
|
||||||
|
break;
|
||||||
|
case "uithermalglow":
|
||||||
|
UIThermalGlow = new UISprite(subElement);
|
||||||
|
break;
|
||||||
case "endroundbuttonpulse":
|
case "endroundbuttonpulse":
|
||||||
ButtonPulse = new UISprite(subElement);
|
ButtonPulse = new UISprite(subElement);
|
||||||
break;
|
break;
|
||||||
|
case "iconoverflowindicator":
|
||||||
|
IconOverflowIndicator = new UISprite(subElement);
|
||||||
|
break;
|
||||||
case "focusindicator":
|
case "focusindicator":
|
||||||
FocusIndicator = new SpriteSheet(subElement);
|
FocusIndicator = new SpriteSheet(subElement);
|
||||||
break;
|
break;
|
||||||
@@ -277,6 +304,10 @@ namespace Barotrauma
|
|||||||
DigitalFont = LoadFont(subElement, graphicsDevice);
|
DigitalFont = LoadFont(subElement, graphicsDevice);
|
||||||
ForceFontUpperCase[DigitalFont] = subElement.GetAttributeBool("forceuppercase", false);
|
ForceFontUpperCase[DigitalFont] = subElement.GetAttributeBool("forceuppercase", false);
|
||||||
break;
|
break;
|
||||||
|
case "monospacedfont":
|
||||||
|
MonospacedFont = LoadFont(subElement, graphicsDevice);
|
||||||
|
ForceFontUpperCase[MonospacedFont] = subElement.GetAttributeBool("forceuppercase", false);
|
||||||
|
break;
|
||||||
case "hotkeyfont":
|
case "hotkeyfont":
|
||||||
HotkeyFont = LoadFont(subElement, graphicsDevice);
|
HotkeyFont = LoadFont(subElement, graphicsDevice);
|
||||||
ForceFontUpperCase[HotkeyFont] = subElement.GetAttributeBool("forceuppercase", false);
|
ForceFontUpperCase[HotkeyFont] = subElement.GetAttributeBool("forceuppercase", false);
|
||||||
@@ -480,5 +511,22 @@ namespace Barotrauma
|
|||||||
|
|
||||||
targetComponent.ApplyStyle(componentStyle);
|
targetComponent.ApplyStyle(componentStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Color GetQualityColor(int quality)
|
||||||
|
{
|
||||||
|
switch (quality)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
return ItemQualityColorGood;
|
||||||
|
case 2:
|
||||||
|
return ItemQualityColorExcellent;
|
||||||
|
case 3:
|
||||||
|
return ItemQualityColorMasterwork;
|
||||||
|
case -1:
|
||||||
|
return ItemQualityColorPoor;
|
||||||
|
default:
|
||||||
|
return ItemQualityColorNormal;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ namespace Barotrauma
|
|||||||
if (GUI.MouseOn != null) { return false; }
|
if (GUI.MouseOn != null) { return false; }
|
||||||
|
|
||||||
//don't close when hovering over an inventory element
|
//don't close when hovering over an inventory element
|
||||||
if (Inventory.IsMouseOnInventory()) { return false; }
|
if (Inventory.IsMouseOnInventory) { return false; }
|
||||||
|
|
||||||
bool input = PlayerInput.PrimaryMouseButtonDown() || PlayerInput.SecondaryMouseButtonClicked();
|
bool input = PlayerInput.PrimaryMouseButtonDown() || PlayerInput.SecondaryMouseButtonClicked();
|
||||||
return input && !rect.Contains(PlayerInput.MousePosition);
|
return input && !rect.Contains(PlayerInput.MousePosition);
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ namespace Barotrauma
|
|||||||
if (LoadState == 100.0f)
|
if (LoadState == 100.0f)
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
if (GameMain.Config.AutomaticQuickStartEnabled || GameMain.Config.AutomaticCampaignLoadEnabled && GameMain.FirstLoad)
|
if (GameMain.Config.AutomaticQuickStartEnabled || GameMain.Config.AutomaticCampaignLoadEnabled || GameMain.Config.TestScreenEnabled && GameMain.FirstLoad)
|
||||||
{
|
{
|
||||||
loadText = "QUICKSTARTING ...";
|
loadText = "QUICKSTARTING ...";
|
||||||
}
|
}
|
||||||
@@ -211,6 +211,13 @@ namespace Barotrauma
|
|||||||
if (LoadState != null)
|
if (LoadState != null)
|
||||||
{
|
{
|
||||||
loadText += " " + (int)LoadState + " %";
|
loadText += " " + (int)LoadState + " %";
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
if (GameMain.FirstLoad && GameMain.CancelQuickStart)
|
||||||
|
{
|
||||||
|
loadText += " (Quickstart aborted)";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (GUI.LargeFont != null)
|
if (GUI.LargeFont != null)
|
||||||
|
|||||||
@@ -55,14 +55,47 @@ namespace Barotrauma
|
|||||||
var texture = GetTexture(spriteBatch);
|
var texture = GetTexture(spriteBatch);
|
||||||
|
|
||||||
for (var i = 0; i < points.Count - 1; i++)
|
for (var i = 0; i < points.Count - 1; i++)
|
||||||
DrawPolygonEdge(spriteBatch, texture, points[i] + offset, points[i + 1] + offset, color, thickness);
|
DrawPolygonEdge(spriteBatch, points[i] + offset, points[i + 1] + offset, color, thickness);
|
||||||
|
|
||||||
DrawPolygonEdge(spriteBatch, texture, points[points.Count - 1] + offset, points[0] + offset, color,
|
DrawPolygonEdge(spriteBatch, points[points.Count - 1] + offset, points[0] + offset, color,
|
||||||
thickness);
|
thickness);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DrawPolygonEdge(SpriteBatch spriteBatch, Texture2D texture, Vector2 point1, Vector2 point2,
|
/// <summary>
|
||||||
Color color, float thickness)
|
/// Draws a closed polygon from an array of points
|
||||||
|
/// </summary>
|
||||||
|
public static void DrawPolygonInner(this SpriteBatch spriteBatch, Vector2 offset, IReadOnlyList<Vector2> points, Color color, float thickness = 1f)
|
||||||
|
{
|
||||||
|
if (points.Count == 0) { return; }
|
||||||
|
|
||||||
|
if (points.Count == 1)
|
||||||
|
{
|
||||||
|
DrawPoint(spriteBatch, points[0], color, (int)thickness);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < points.Count - 1; i++)
|
||||||
|
{
|
||||||
|
Vector2 point1 = points[i] + offset,
|
||||||
|
point2 = points[i + 1] + offset;
|
||||||
|
|
||||||
|
DrawPolygonEdgeInner(spriteBatch, point1, point2, color, thickness);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawPolygonEdgeInner(spriteBatch, points[^1] + offset, points[0] + offset, color, thickness);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DrawPolygonEdgeInner(SpriteBatch spriteBatch, Vector2 point1, Vector2 point2, Color color, float thickness)
|
||||||
|
{
|
||||||
|
var length = Vector2.Distance(point1, point2) + thickness;
|
||||||
|
var angle = (float)Math.Atan2(point2.Y - point1.Y, point2.X - point1.X);
|
||||||
|
var scale = new Vector2(length, thickness);
|
||||||
|
Vector2 middle = new Vector2((point1.X + point2.X) / 2f, (point1.Y + point2.Y) / 2f);
|
||||||
|
Texture2D tex = GetTexture(spriteBatch);
|
||||||
|
spriteBatch.Draw(GetTexture(spriteBatch), middle, null, color, angle, new Vector2(tex.Width / 2f, tex.Height / 2f), scale, SpriteEffects.None, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DrawPolygonEdge(SpriteBatch spriteBatch, Vector2 point1, Vector2 point2, Color color, float thickness)
|
||||||
{
|
{
|
||||||
var length = Vector2.Distance(point1, point2);
|
var length = Vector2.Distance(point1, point2);
|
||||||
var angle = (float)Math.Atan2(point2.Y - point1.Y, point2.X - point1.X);
|
var angle = (float)Math.Atan2(point2.Y - point1.Y, point2.X - point1.X);
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace Barotrauma
|
|||||||
private Color storeSpecialColor;
|
private Color storeSpecialColor;
|
||||||
|
|
||||||
private GUIListBox shoppingCrateBuyList, shoppingCrateSellList, shoppingCrateSellFromSubList;
|
private GUIListBox shoppingCrateBuyList, shoppingCrateSellList, shoppingCrateSellFromSubList;
|
||||||
private GUITextBlock shoppingCrateTotal;
|
private GUITextBlock relevantBalanceName, shoppingCrateTotal;
|
||||||
private GUIButton clearAllButton, confirmButton;
|
private GUIButton clearAllButton, confirmButton;
|
||||||
|
|
||||||
private bool needsRefresh, needsBuyingRefresh, needsSellingRefresh, needsItemsToSellRefresh, needsSellingFromSubRefresh, needsItemsToSellFromSubRefresh;
|
private bool needsRefresh, needsBuyingRefresh, needsSellingRefresh, needsItemsToSellRefresh, needsSellingFromSubRefresh, needsItemsToSellFromSubRefresh;
|
||||||
@@ -58,7 +58,6 @@ namespace Barotrauma
|
|||||||
StoreTab.SellFromSub => false,
|
StoreTab.SellFromSub => false,
|
||||||
_ => throw new NotImplementedException()
|
_ => throw new NotImplementedException()
|
||||||
};
|
};
|
||||||
private bool IsSelling => !IsBuying;
|
|
||||||
private GUIListBox ActiveShoppingCrateList => activeTab switch
|
private GUIListBox ActiveShoppingCrateList => activeTab switch
|
||||||
{
|
{
|
||||||
StoreTab.Buy => shoppingCrateBuyList,
|
StoreTab.Buy => shoppingCrateBuyList,
|
||||||
@@ -222,16 +221,8 @@ namespace Barotrauma
|
|||||||
TextScale = 1.1f,
|
TextScale = 1.1f,
|
||||||
TextGetter = () =>
|
TextGetter = () =>
|
||||||
{
|
{
|
||||||
if (CurrentLocation != null)
|
merchantBalanceBlock.TextColor = CurrentLocation?.BalanceColor ?? Color.Red;
|
||||||
{
|
return GetMerchantBalanceText();
|
||||||
merchantBalanceBlock.TextColor = CurrentLocation.BalanceColor;
|
|
||||||
return GetCurrencyFormatted(CurrentLocation.StoreCurrentBalance);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
merchantBalanceBlock.TextColor = Color.Red;
|
|
||||||
return GetCurrencyFormatted(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -375,28 +366,37 @@ namespace Barotrauma
|
|||||||
//don't show categories with no buyable items
|
//don't show categories with no buyable items
|
||||||
itemCategories.RemoveAll(c => !ItemPrefab.Prefabs.Any(ep => ep.Category.HasFlag(c) && ep.CanBeBought));
|
itemCategories.RemoveAll(c => !ItemPrefab.Prefabs.Any(ep => ep.Category.HasFlag(c) && ep.CanBeBought));
|
||||||
itemCategoryButtons.Clear();
|
itemCategoryButtons.Clear();
|
||||||
|
var categoryButton = new GUIButton(new RectTransform(new Point(categoryButtonContainer.Rect.Width, categoryButtonContainer.Rect.Width), categoryButtonContainer.RectTransform), style: "CategoryButton.All")
|
||||||
|
{
|
||||||
|
ToolTip = TextManager.Get("MapEntityCategory.All"),
|
||||||
|
OnClicked = OnClickedCategoryButton
|
||||||
|
};
|
||||||
|
itemCategoryButtons.Add(categoryButton);
|
||||||
foreach (MapEntityCategory category in itemCategories)
|
foreach (MapEntityCategory category in itemCategories)
|
||||||
{
|
{
|
||||||
var categoryButton = new GUIButton(new RectTransform(new Point(categoryButtonContainer.Rect.Width, categoryButtonContainer.Rect.Width), categoryButtonContainer.RectTransform),
|
categoryButton = new GUIButton(new RectTransform(new Point(categoryButtonContainer.Rect.Width, categoryButtonContainer.Rect.Width), categoryButtonContainer.RectTransform),
|
||||||
style: "CategoryButton." + category)
|
style: "CategoryButton." + category)
|
||||||
{
|
{
|
||||||
ToolTip = TextManager.Get("MapEntityCategory." + category),
|
ToolTip = TextManager.Get("MapEntityCategory." + category),
|
||||||
UserData = category,
|
UserData = category,
|
||||||
OnClicked = (btn, userdata) =>
|
OnClicked = OnClickedCategoryButton
|
||||||
{
|
|
||||||
MapEntityCategory? newCategory = !btn.Selected ? (MapEntityCategory?)userdata : null;
|
|
||||||
if (newCategory.HasValue) { searchBox.Text = ""; }
|
|
||||||
if (newCategory != selectedItemCategory) { tabLists[activeTab].ScrollBar.BarScroll = 0f; }
|
|
||||||
FilterStoreItems(newCategory, searchBox.Text);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
itemCategoryButtons.Add(categoryButton);
|
itemCategoryButtons.Add(categoryButton);
|
||||||
categoryButton.RectTransform.SizeChanged += () =>
|
}
|
||||||
|
bool OnClickedCategoryButton(GUIButton button, object userData)
|
||||||
|
{
|
||||||
|
MapEntityCategory? newCategory = !button.Selected ? (MapEntityCategory?)userData : null;
|
||||||
|
if (newCategory.HasValue) { searchBox.Text = ""; }
|
||||||
|
if (newCategory != selectedItemCategory) { tabLists[activeTab].ScrollBar.BarScroll = 0f; }
|
||||||
|
FilterStoreItems(newCategory, searchBox.Text);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
foreach (var btn in itemCategoryButtons)
|
||||||
|
{
|
||||||
|
btn.RectTransform.SizeChanged += () =>
|
||||||
{
|
{
|
||||||
var sprite = categoryButton.Frame.sprites[GUIComponent.ComponentState.None].First();
|
var sprite = btn.Frame.sprites[GUIComponent.ComponentState.None].First();
|
||||||
categoryButton.RectTransform.NonScaledSize =
|
btn.RectTransform.NonScaledSize = new Point(btn.Rect.Width, (int)(btn.Rect.Width * ((float)sprite.Sprite.SourceRect.Height / sprite.Sprite.SourceRect.Width)));
|
||||||
new Point(categoryButton.Rect.Width, (int)(categoryButton.Rect.Width * ((float)sprite.Sprite.SourceRect.Height / sprite.Sprite.SourceRect.Width)));
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -503,11 +503,11 @@ namespace Barotrauma
|
|||||||
ForceUpperCase = true
|
ForceUpperCase = true
|
||||||
};
|
};
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), playerBalanceContainer.RectTransform),
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), playerBalanceContainer.RectTransform),
|
||||||
"", font: GUI.SubHeadingFont, textAlignment: Alignment.TopRight)
|
"", textColor: Color.White, font: GUI.SubHeadingFont, textAlignment: Alignment.TopRight)
|
||||||
{
|
{
|
||||||
AutoScaleVertical = true,
|
AutoScaleVertical = true,
|
||||||
TextScale = 1.1f,
|
TextScale = 1.1f,
|
||||||
TextGetter = () => GetCurrencyFormatted(PlayerMoney)
|
TextGetter = GetPlayerBalanceText
|
||||||
};
|
};
|
||||||
|
|
||||||
// Divider ------------------------------------------------
|
// Divider ------------------------------------------------
|
||||||
@@ -523,7 +523,7 @@ namespace Barotrauma
|
|||||||
RelativeSpacing = 0.015f,
|
RelativeSpacing = 0.015f,
|
||||||
Stretch = true
|
Stretch = true
|
||||||
};
|
};
|
||||||
var shoppingCrateListContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.85f), shoppingCrateInventoryContainer.RectTransform), style: null);
|
var shoppingCrateListContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.8f), shoppingCrateInventoryContainer.RectTransform), style: null);
|
||||||
shoppingCrateBuyList = new GUIListBox(new RectTransform(Vector2.One, shoppingCrateListContainer.RectTransform)) { Visible = false };
|
shoppingCrateBuyList = new GUIListBox(new RectTransform(Vector2.One, shoppingCrateListContainer.RectTransform)) { Visible = false };
|
||||||
shoppingCrateSellList = new GUIListBox(new RectTransform(Vector2.One, shoppingCrateListContainer.RectTransform)) { Visible = false };
|
shoppingCrateSellList = new GUIListBox(new RectTransform(Vector2.One, shoppingCrateListContainer.RectTransform)) { Visible = false };
|
||||||
if (GameMain.IsSingleplayer)
|
if (GameMain.IsSingleplayer)
|
||||||
@@ -531,6 +531,21 @@ namespace Barotrauma
|
|||||||
shoppingCrateSellFromSubList = new GUIListBox(new RectTransform(Vector2.One, shoppingCrateListContainer.RectTransform)) { Visible = false };
|
shoppingCrateSellFromSubList = new GUIListBox(new RectTransform(Vector2.One, shoppingCrateListContainer.RectTransform)) { Visible = false };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var relevantBalanceContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), shoppingCrateInventoryContainer.RectTransform), isHorizontal: true)
|
||||||
|
{
|
||||||
|
Stretch = true
|
||||||
|
};
|
||||||
|
relevantBalanceName = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), relevantBalanceContainer.RectTransform), "", font: GUI.Font)
|
||||||
|
{
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), relevantBalanceContainer.RectTransform), "", textColor: Color.White, font: GUI.SubHeadingFont, textAlignment: Alignment.Right)
|
||||||
|
{
|
||||||
|
CanBeFocused = false,
|
||||||
|
TextScale = 1.1f,
|
||||||
|
TextGetter = () => IsBuying ? GetPlayerBalanceText() : GetMerchantBalanceText()
|
||||||
|
};
|
||||||
|
|
||||||
var totalContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), shoppingCrateInventoryContainer.RectTransform), isHorizontal: true)
|
var totalContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), shoppingCrateInventoryContainer.RectTransform), isHorizontal: true)
|
||||||
{
|
{
|
||||||
Stretch = true
|
Stretch = true
|
||||||
@@ -576,10 +591,14 @@ namespace Barotrauma
|
|||||||
resolutionWhenCreated = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
resolutionWhenCreated = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GUILayoutGroup CreateDealsGroup(GUIListBox parentList)
|
private string GetMerchantBalanceText() => GetCurrencyFormatted(CurrentLocation?.StoreCurrentBalance ?? 0);
|
||||||
|
|
||||||
|
private string GetPlayerBalanceText() => GetCurrencyFormatted(PlayerMoney);
|
||||||
|
|
||||||
|
private GUILayoutGroup CreateDealsGroup(GUIListBox parentList, int elementCount = 4)
|
||||||
{
|
{
|
||||||
var elementHeight = (int)(GUI.yScale * 80);
|
var elementHeight = (int)(GUI.yScale * 80);
|
||||||
var frame = new GUIFrame(new RectTransform(new Point(parentList.Content.Rect.Width, 4 * elementHeight + 3), parent: parentList.Content.RectTransform), style: null);
|
var frame = new GUIFrame(new RectTransform(new Point(parentList.Content.Rect.Width, elementCount * elementHeight + 3), parent: parentList.Content.RectTransform), style: null);
|
||||||
frame.UserData = "deals";
|
frame.UserData = "deals";
|
||||||
var dealsGroup = new GUILayoutGroup(new RectTransform(Vector2.One, frame.RectTransform, anchor: Anchor.Center), childAnchor: Anchor.TopCenter);
|
var dealsGroup = new GUILayoutGroup(new RectTransform(Vector2.One, frame.RectTransform, anchor: Anchor.Center), childAnchor: Anchor.TopCenter);
|
||||||
var dealsHeader = new GUILayoutGroup(new RectTransform(new Point((int)(0.95f * parentList.Content.Rect.Width), elementHeight), parent: dealsGroup.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft);
|
var dealsHeader = new GUILayoutGroup(new RectTransform(new Point((int)(0.95f * parentList.Content.Rect.Width), elementHeight), parent: dealsGroup.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft);
|
||||||
@@ -604,17 +623,14 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
prevLocation.Reputation.OnReputationValueChanged = null;
|
prevLocation.Reputation.OnReputationValueChanged = null;
|
||||||
}
|
}
|
||||||
|
if (ItemPrefab.Prefabs.Any(p => p.CanBeBoughtAtLocation(CurrentLocation, out PriceInfo _)))
|
||||||
foreach (ItemPrefab itemPrefab in ItemPrefab.Prefabs)
|
|
||||||
{
|
{
|
||||||
if (itemPrefab.CanBeBoughtAtLocation(CurrentLocation, out PriceInfo _))
|
selectedItemCategory = null;
|
||||||
|
searchBox.Text = "";
|
||||||
|
ChangeStoreTab(StoreTab.Buy);
|
||||||
|
if (newLocation?.Reputation != null)
|
||||||
{
|
{
|
||||||
ChangeStoreTab(StoreTab.Buy);
|
newLocation.Reputation.OnReputationValueChanged += () => { needsRefresh = true; };
|
||||||
if (newLocation?.Reputation != null)
|
|
||||||
{
|
|
||||||
newLocation.Reputation.OnReputationValueChanged += () => { needsRefresh = true; };
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -628,6 +644,7 @@ namespace Barotrauma
|
|||||||
tabButton.Selected = (StoreTab)tabButton.UserData == activeTab;
|
tabButton.Selected = (StoreTab)tabButton.UserData == activeTab;
|
||||||
}
|
}
|
||||||
sortingDropDown.SelectItem(tabSortingMethods[tab]);
|
sortingDropDown.SelectItem(tabSortingMethods[tab]);
|
||||||
|
relevantBalanceName.Text = IsBuying ? TextManager.Get("campaignstore.balance") : TextManager.Get("campaignstore.storebalance");
|
||||||
SetShoppingCrateTotalText();
|
SetShoppingCrateTotalText();
|
||||||
SetClearAllButtonStatus();
|
SetClearAllButtonStatus();
|
||||||
SetConfirmButtonBehavior();
|
SetConfirmButtonBehavior();
|
||||||
@@ -697,7 +714,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
foreach (GUIButton btn in itemCategoryButtons)
|
foreach (GUIButton btn in itemCategoryButtons)
|
||||||
{
|
{
|
||||||
btn.Selected = category.HasValue && (MapEntityCategory)btn.UserData == selectedItemCategory;
|
btn.Selected = (MapEntityCategory?)btn.UserData == selectedItemCategory;
|
||||||
}
|
}
|
||||||
list.UpdateScrollBarSize();
|
list.UpdateScrollBarSize();
|
||||||
}
|
}
|
||||||
@@ -709,6 +726,8 @@ namespace Barotrauma
|
|||||||
FilterStoreItems(category, searchBox.Text);
|
FilterStoreItems(category, searchBox.Text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int prevDailySpecialCount;
|
||||||
|
|
||||||
private void RefreshStoreBuyList()
|
private void RefreshStoreBuyList()
|
||||||
{
|
{
|
||||||
float prevBuyListScroll = storeBuyList.BarScroll;
|
float prevBuyListScroll = storeBuyList.BarScroll;
|
||||||
@@ -717,11 +736,14 @@ namespace Barotrauma
|
|||||||
bool hasPermissions = HasPermissions;
|
bool hasPermissions = HasPermissions;
|
||||||
HashSet<GUIComponent> existingItemFrames = new HashSet<GUIComponent>();
|
HashSet<GUIComponent> existingItemFrames = new HashSet<GUIComponent>();
|
||||||
|
|
||||||
if ((storeDailySpecialsGroup != null) != CurrentLocation.DailySpecials.Any())
|
int dailySpecialCount = CurrentLocation?.DailySpecials.Count() ?? 3;
|
||||||
|
|
||||||
|
if ((storeDailySpecialsGroup != null) != CurrentLocation.DailySpecials.Any() || dailySpecialCount != prevDailySpecialCount)
|
||||||
{
|
{
|
||||||
if (storeDailySpecialsGroup == null)
|
if (storeDailySpecialsGroup == null || dailySpecialCount != prevDailySpecialCount)
|
||||||
{
|
{
|
||||||
storeDailySpecialsGroup = CreateDealsGroup(storeBuyList);
|
storeBuyList.RemoveChild(storeDailySpecialsGroup?.Parent);
|
||||||
|
storeDailySpecialsGroup = CreateDealsGroup(storeBuyList, 1 + dailySpecialCount);
|
||||||
storeDailySpecialsGroup.Parent.SetAsFirstChild();
|
storeDailySpecialsGroup.Parent.SetAsFirstChild();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -730,6 +752,7 @@ namespace Barotrauma
|
|||||||
storeDailySpecialsGroup = null;
|
storeDailySpecialsGroup = null;
|
||||||
}
|
}
|
||||||
storeBuyList.RecalculateChildren();
|
storeBuyList.RecalculateChildren();
|
||||||
|
prevDailySpecialCount = dailySpecialCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (PurchasedItem item in CurrentLocation.StoreStock)
|
foreach (PurchasedItem item in CurrentLocation.StoreStock)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -18,8 +19,8 @@ namespace Barotrauma
|
|||||||
private static UISprite spectateIcon, disconnectedIcon;
|
private static UISprite spectateIcon, disconnectedIcon;
|
||||||
private static Sprite ownerIcon, moderatorIcon;
|
private static Sprite ownerIcon, moderatorIcon;
|
||||||
|
|
||||||
private enum InfoFrameTab { Crew, Mission, Reputation, MyCharacter, Traitor, Submarine };
|
public enum InfoFrameTab { Crew, Mission, Reputation, Traitor, Submarine, Talents };
|
||||||
private static InfoFrameTab selectedTab;
|
public static InfoFrameTab selectedTab;
|
||||||
private GUIFrame infoFrame, contentFrame;
|
private GUIFrame infoFrame, contentFrame;
|
||||||
|
|
||||||
private readonly List<GUIButton> tabButtons = new List<GUIButton>();
|
private readonly List<GUIButton> tabButtons = new List<GUIButton>();
|
||||||
@@ -33,6 +34,8 @@ namespace Barotrauma
|
|||||||
private List<CharacterTeamType> teamIDs;
|
private List<CharacterTeamType> teamIDs;
|
||||||
private const string inLobbyString = "\u2022 \u2022 \u2022";
|
private const string inLobbyString = "\u2022 \u2022 \u2022";
|
||||||
|
|
||||||
|
private GUIFrame pendingChangesFrame = null;
|
||||||
|
|
||||||
public static Color OwnCharacterBGColor = Color.Gold * 0.7f;
|
public static Color OwnCharacterBGColor = Color.Gold * 0.7f;
|
||||||
|
|
||||||
private class LinkedGUI
|
private class LinkedGUI
|
||||||
@@ -125,7 +128,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public TabMenu()
|
public TabMenu()
|
||||||
{
|
{
|
||||||
if (!initialized) Initialize();
|
if (!initialized) { Initialize(); }
|
||||||
|
|
||||||
CreateInfoFrame(selectedTab);
|
CreateInfoFrame(selectedTab);
|
||||||
SelectInfoFrameTab(null, selectedTab);
|
SelectInfoFrameTab(null, selectedTab);
|
||||||
@@ -133,6 +136,17 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
|
GameSession.UpdateTalentNotificationIndicator(talentPointNotification);
|
||||||
|
if (Character.Controlled is { } controlled && talentResetButton != null && talentApplyButton != null)
|
||||||
|
{
|
||||||
|
int talentCount = selectedTalents.Count - controlled.Info.GetUnlockedTalentsInTree().Count();
|
||||||
|
talentResetButton.Enabled = talentApplyButton.Enabled = talentCount > 0;
|
||||||
|
if (talentApplyButton.Enabled && talentApplyButton.FlashTimer <= 0.0f)
|
||||||
|
{
|
||||||
|
talentApplyButton.Flash(GUI.Style.Orange);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (selectedTab != InfoFrameTab.Crew) return;
|
if (selectedTab != InfoFrameTab.Crew) return;
|
||||||
if (linkedGUIList == null) return;
|
if (linkedGUIList == null) return;
|
||||||
|
|
||||||
@@ -182,16 +196,8 @@ namespace Barotrauma
|
|||||||
new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, infoFrame.RectTransform, Anchor.Center), style: "GUIBackgroundBlocker");
|
new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, infoFrame.RectTransform, Anchor.Center), style: "GUIBackgroundBlocker");
|
||||||
|
|
||||||
//this used to be a switch expression but i changed it because it killed enc :(
|
//this used to be a switch expression but i changed it because it killed enc :(
|
||||||
Vector2 contentFrameSize;
|
//now it's not even a switch statement anymore :(
|
||||||
switch (selectedTab)
|
Vector2 contentFrameSize = new Vector2(0.45f, 0.667f);
|
||||||
{
|
|
||||||
case InfoFrameTab.MyCharacter:
|
|
||||||
contentFrameSize = new Vector2(0.45f, 0.5f);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
contentFrameSize = new Vector2(0.45f, 0.667f);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
contentFrame = new GUIFrame(new RectTransform(contentFrameSize, infoFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.12f) });
|
contentFrame = new GUIFrame(new RectTransform(contentFrameSize, infoFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.12f) });
|
||||||
|
|
||||||
var horizontalLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.958f, 0.943f), contentFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, GUI.IntScale(25f)) }, isHorizontal: true)
|
var horizontalLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.958f, 0.943f), contentFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, GUI.IntScale(25f)) }, isHorizontal: true)
|
||||||
@@ -242,6 +248,17 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
TextGetter = () => TextManager.GetWithVariable("campaignmoney", "[money]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", campaignMode.Money))
|
TextGetter = () => TextManager.GetWithVariable("campaignmoney", "[money]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", campaignMode.Money))
|
||||||
};
|
};
|
||||||
|
GUIFrame bottomDisclaimerFrame = new GUIFrame(new RectTransform(new Vector2(contentFrameSize.X, 0.1f), infoFrame.RectTransform)
|
||||||
|
{
|
||||||
|
AbsoluteOffset = new Point(contentFrame.Rect.X, contentFrame.Rect.Bottom + GUI.IntScale(8))
|
||||||
|
}, style: null);
|
||||||
|
|
||||||
|
pendingChangesFrame = new GUIFrame(new RectTransform(Vector2.One, bottomDisclaimerFrame.RectTransform, Anchor.Center), style: null);
|
||||||
|
|
||||||
|
if (GameMain.NetLobbyScreen?.CampaignCharacterDiscarded ?? false)
|
||||||
|
{
|
||||||
|
NetLobbyScreen.CreateChangesPendingFrame(pendingChangesFrame);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -254,10 +271,17 @@ namespace Barotrauma
|
|||||||
|
|
||||||
var submarineButton = createTabButton(InfoFrameTab.Submarine, "submarine");
|
var submarineButton = createTabButton(InfoFrameTab.Submarine, "submarine");
|
||||||
|
|
||||||
if (GameMain.NetworkMember != null)
|
var talentsButton = createTabButton(InfoFrameTab.Talents, "tabmenu.character");
|
||||||
|
talentsButton.OnAddedToGUIUpdateList += (component) =>
|
||||||
{
|
{
|
||||||
var myCharacterButton = createTabButton(InfoFrameTab.MyCharacter, "tabmenu.character");
|
talentsButton.Enabled = Character.Controlled?.Info != null;
|
||||||
}
|
if (!talentsButton.Enabled && selectedTab == InfoFrameTab.Talents)
|
||||||
|
{
|
||||||
|
SelectInfoFrameTab(null, InfoFrameTab.Crew);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
talentPointNotification = GameSession.CreateTalentIconNotification(talentsButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool SelectInfoFrameTab(GUIButton button, object userData)
|
private bool SelectInfoFrameTab(GUIButton button, object userData)
|
||||||
@@ -289,13 +313,12 @@ namespace Barotrauma
|
|||||||
if (traitor == null || traitorMission == null) return false;
|
if (traitor == null || traitorMission == null) return false;
|
||||||
CreateTraitorInfo(infoFrameHolder, traitorMission, traitor);
|
CreateTraitorInfo(infoFrameHolder, traitorMission, traitor);
|
||||||
break;
|
break;
|
||||||
case InfoFrameTab.MyCharacter:
|
|
||||||
if (GameMain.NetworkMember == null) { return false; }
|
|
||||||
GameMain.NetLobbyScreen.CreatePlayerFrame(infoFrameHolder);
|
|
||||||
break;
|
|
||||||
case InfoFrameTab.Submarine:
|
case InfoFrameTab.Submarine:
|
||||||
CreateSubmarineInfo(infoFrameHolder, Submarine.MainSub);
|
CreateSubmarineInfo(infoFrameHolder, Submarine.MainSub);
|
||||||
break;
|
break;
|
||||||
|
case InfoFrameTab.Talents:
|
||||||
|
CreateTalentInfo(infoFrameHolder);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -1159,5 +1182,506 @@ namespace Barotrauma
|
|||||||
sub.Info.CreateSpecsWindow(specsListBox, GUI.Font, includeTitle: false, includeClass: false, includeDescription: true);
|
sub.Info.CreateSpecsWindow(specsListBox, GUI.Font, includeTitle: false, includeClass: false, includeDescription: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private Color unselectedColor = new Color(240, 255, 255, 225);
|
||||||
|
private Color selectedColor = new Color(220, 255, 220, 225);
|
||||||
|
private Color ownedColor = new Color(140, 180, 140, 225);
|
||||||
|
private Color unselectableColor = new Color(100, 100, 100, 225);
|
||||||
|
private Color pressedColor = new Color(60, 60, 60, 225);
|
||||||
|
|
||||||
|
private readonly List<(GUIButton button, GUIComponent icon)> talentButtons = new List<(GUIButton button, GUIComponent icon)>();
|
||||||
|
private readonly List<(string talentTree, int index, GUIImage icon, GUIFrame background, GUIFrame backgroundGlow)> talentCornerIcons = new List<(string talentTree, int index, GUIImage icon, GUIFrame background, GUIFrame backgroundGlow)>();
|
||||||
|
private List<string> selectedTalents = new List<string>();
|
||||||
|
|
||||||
|
private GUITextBlock experienceText;
|
||||||
|
private GUIProgressBar experienceBar;
|
||||||
|
private GUITextBlock talentPointText;
|
||||||
|
private GUIListBox skillListBox;
|
||||||
|
|
||||||
|
private GUIButton talentApplyButton,
|
||||||
|
talentResetButton;
|
||||||
|
|
||||||
|
private GUIImage talentPointNotification;
|
||||||
|
|
||||||
|
private readonly ImmutableDictionary<TalentTree.TalentTreeStageState, GUIComponentStyle> talentStageStyles = new Dictionary<TalentTree.TalentTreeStageState, GUIComponentStyle>
|
||||||
|
{
|
||||||
|
{ TalentTree.TalentTreeStageState.Invalid, GUI.Style.GetComponentStyle("TalentTreeLocked") },
|
||||||
|
{ TalentTree.TalentTreeStageState.Locked, GUI.Style.GetComponentStyle("TalentTreeLocked") },
|
||||||
|
{ TalentTree.TalentTreeStageState.Unlocked, GUI.Style.GetComponentStyle("TalentTreePurchased") },
|
||||||
|
{ TalentTree.TalentTreeStageState.Available, GUI.Style.GetComponentStyle("TalentTreeUnlocked") },
|
||||||
|
{ TalentTree.TalentTreeStageState.Highlighted, GUI.Style.GetComponentStyle("TalentTreeAvailable") },
|
||||||
|
}.ToImmutableDictionary();
|
||||||
|
|
||||||
|
private readonly ImmutableDictionary<TalentTree.TalentTreeStageState, Color> talentStageBackgroundColors = new Dictionary<TalentTree.TalentTreeStageState, Color>
|
||||||
|
{
|
||||||
|
{ TalentTree.TalentTreeStageState.Invalid, new Color(48,48,48,255) },
|
||||||
|
{ TalentTree.TalentTreeStageState.Locked, new Color(48,48,48,255) },
|
||||||
|
{ TalentTree.TalentTreeStageState.Unlocked, new Color(24,37,31,255) },
|
||||||
|
{ TalentTree.TalentTreeStageState.Available, new Color(50,47,33,255) },
|
||||||
|
{ TalentTree.TalentTreeStageState.Highlighted, new Color(50,47,33,255) },
|
||||||
|
}.ToImmutableDictionary();
|
||||||
|
|
||||||
|
private void CreateTalentInfo(GUIFrame infoFrame)
|
||||||
|
{
|
||||||
|
infoFrame.ClearChildren();
|
||||||
|
talentButtons.Clear();
|
||||||
|
talentCornerIcons.Clear();
|
||||||
|
|
||||||
|
Character controlledCharacter = Character.Controlled;
|
||||||
|
if (controlledCharacter == null) { return; }
|
||||||
|
|
||||||
|
GUIFrame talentFrameBackground = new GUIFrame(new RectTransform(Vector2.One, infoFrame.RectTransform, Anchor.TopCenter), style: "GUIFrameListBox");
|
||||||
|
int padding = GUI.IntScale(15);
|
||||||
|
GUIFrame talentFrameContent = new GUIFrame(new RectTransform(new Point(talentFrameBackground.Rect.Width - padding, talentFrameBackground.Rect.Height - padding), infoFrame.RectTransform, Anchor.Center), style: null);
|
||||||
|
|
||||||
|
GUIFrame paddedTalentFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.9f), talentFrameContent.RectTransform, Anchor.Center), style: null);
|
||||||
|
|
||||||
|
GUIFrame talentFrameMain = new GUIFrame(new RectTransform(Vector2.One, paddedTalentFrame.RectTransform), style: null);
|
||||||
|
|
||||||
|
GUIFrame characterSettingsFrame = null;
|
||||||
|
GUILayoutGroup characterLayout = null;
|
||||||
|
if (!(GameMain.NetworkMember is null))
|
||||||
|
{
|
||||||
|
characterSettingsFrame = new GUIFrame(new RectTransform(Vector2.One, talentFrameContent.RectTransform), style: null) { Visible = false };
|
||||||
|
characterLayout = new GUILayoutGroup(new RectTransform(Vector2.One, characterSettingsFrame.RectTransform));
|
||||||
|
GUIFrame containerFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.9f), characterLayout.RectTransform), style: null);
|
||||||
|
GUIFrame playerFrame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.7f), containerFrame.RectTransform, Anchor.Center), style: null);
|
||||||
|
GameMain.NetLobbyScreen.CreatePlayerFrame(playerFrame, alwaysAllowEditing: true, createPendingText: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (controlledCharacter.Info is null)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("No character info found for talent UI");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedTalents = controlledCharacter.Info.GetUnlockedTalentsInTree().ToList();
|
||||||
|
|
||||||
|
GUILayoutGroup talentFrameLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), talentFrameMain.RectTransform, anchor: Anchor.Center), childAnchor: Anchor.TopCenter)
|
||||||
|
{
|
||||||
|
AbsoluteSpacing = GUI.IntScale(5)
|
||||||
|
};
|
||||||
|
|
||||||
|
GUILayoutGroup talentInfoLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), talentFrameLayoutGroup.RectTransform, Anchor.Center), isHorizontal: true);
|
||||||
|
|
||||||
|
CharacterInfo info = controlledCharacter.Info;
|
||||||
|
Job job = info.Job;
|
||||||
|
|
||||||
|
new GUICustomComponent(new RectTransform(new Vector2(0.25f, 1f), talentInfoLayoutGroup.RectTransform), onDraw: (batch, component) =>
|
||||||
|
{
|
||||||
|
float posY = component.Rect.Center.Y - component.Rect.Width / 2;
|
||||||
|
info.DrawPortrait(batch, new Vector2(component.Rect.X, posY), Vector2.Zero, component.Rect.Width, false, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
GUILayoutGroup nameLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.3f, 1f), talentInfoLayoutGroup.RectTransform)) { RelativeSpacing = 0.05f };
|
||||||
|
|
||||||
|
Vector2 nameSize = GUI.SubHeadingFont.MeasureString(info.Name);
|
||||||
|
GUITextBlock nameBlock = new GUITextBlock(new RectTransform(Vector2.One, nameLayout.RectTransform), info.Name, font: GUI.SubHeadingFont) { TextColor = job.Prefab.UIColor };
|
||||||
|
nameBlock.RectTransform.NonScaledSize = nameSize.Pad(nameBlock.Padding).ToPoint();
|
||||||
|
|
||||||
|
Vector2 jobSize = GUI.SmallFont.MeasureString(job.Name);
|
||||||
|
GUITextBlock jobBlock = new GUITextBlock(new RectTransform(Vector2.One, nameLayout.RectTransform), job.Name, font: GUI.SmallFont) { TextColor = job.Prefab.UIColor };
|
||||||
|
jobBlock.RectTransform.NonScaledSize = jobSize.Pad(jobBlock.Padding).ToPoint();
|
||||||
|
|
||||||
|
string traitString = TextManager.AddPunctuation(':', TextManager.Get("PersonalityTrait"), TextManager.Get("personalitytrait." + info.PersonalityTrait.Name.Replace(" ", "")));
|
||||||
|
Vector2 traitSize = GUI.SmallFont.MeasureString(traitString);
|
||||||
|
GUITextBlock traitBlock = new GUITextBlock(new RectTransform(Vector2.One, nameLayout.RectTransform), traitString, font: GUI.SmallFont);
|
||||||
|
traitBlock.RectTransform.NonScaledSize = traitSize.Pad(traitBlock.Padding).ToPoint();
|
||||||
|
|
||||||
|
GUIFrame endocrineFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.35f), nameLayout.RectTransform, Anchor.BottomCenter), style: null);
|
||||||
|
|
||||||
|
if (!(GameMain.NetworkMember is null))
|
||||||
|
{
|
||||||
|
GUIButton newCharacterBox = new GUIButton(new RectTransform(new Vector2(0.675f, 1f), endocrineFrame.RectTransform, Anchor.TopLeft), text: GameMain.NetLobbyScreen.CampaignCharacterDiscarded ? TextManager.Get("settings") : TextManager.Get("createnew"))
|
||||||
|
{
|
||||||
|
IgnoreLayoutGroups = true
|
||||||
|
};
|
||||||
|
|
||||||
|
newCharacterBox.OnClicked = (button, o) =>
|
||||||
|
{
|
||||||
|
if (!GameMain.NetLobbyScreen.CampaignCharacterDiscarded)
|
||||||
|
{
|
||||||
|
GameMain.NetLobbyScreen.TryDiscardCampaignCharacter(() =>
|
||||||
|
{
|
||||||
|
newCharacterBox.Text = TextManager.Get("settings");
|
||||||
|
|
||||||
|
if (pendingChangesFrame != null)
|
||||||
|
{
|
||||||
|
NetLobbyScreen.CreateChangesPendingFrame(pendingChangesFrame);
|
||||||
|
}
|
||||||
|
OpenMenu();
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenMenu();
|
||||||
|
return true;
|
||||||
|
|
||||||
|
void OpenMenu()
|
||||||
|
{
|
||||||
|
characterSettingsFrame!.Visible = true;
|
||||||
|
talentFrameMain.Visible = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!(characterLayout is null))
|
||||||
|
{
|
||||||
|
GUILayoutGroup characterCloseButtonLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.1f), characterLayout.RectTransform), childAnchor: Anchor.BottomRight);
|
||||||
|
new GUIButton(new RectTransform(new Vector2(0.4f, 1f), characterCloseButtonLayout.RectTransform), TextManager.Get("ApplySettingsButton")) //TODO: Is this text appropriate for this circumstance for all languages?
|
||||||
|
{
|
||||||
|
OnClicked = (button, o) =>
|
||||||
|
{
|
||||||
|
characterSettingsFrame!.Visible = false;
|
||||||
|
talentFrameMain.Visible = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable<TalentPrefab> endocrineTalents = info.GetEndocrineTalents().Select(e => TalentPrefab.TalentPrefabs.Find(c => c.Identifier.Equals(e, StringComparison.OrdinalIgnoreCase)));
|
||||||
|
|
||||||
|
if (endocrineTalents.Count() > 0)
|
||||||
|
{
|
||||||
|
GUIImage endocrineIcon = new GUIImage(new RectTransform(new Vector2(0.275f, 1f), endocrineFrame.RectTransform, anchor: Anchor.TopRight, scaleBasis: ScaleBasis.Normal), style: "EndocrineReminderIcon")
|
||||||
|
{
|
||||||
|
ToolTip = $"{TextManager.Get("afflictionname.endocrineboost")}\n\n{string.Join(", ", endocrineTalents.Select(e => e.DisplayName))}"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayoutGroup skillLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.45f, 1f), talentInfoLayoutGroup.RectTransform)) { Stretch = true };
|
||||||
|
|
||||||
|
string skillString = TextManager.Get("skills");
|
||||||
|
Vector2 skillSize = GUI.SubHeadingFont.MeasureString(skillString);
|
||||||
|
GUITextBlock skillBlock = new GUITextBlock(new RectTransform(Vector2.One, skillLayout.RectTransform), skillString, font: GUI.SubHeadingFont);
|
||||||
|
skillBlock.RectTransform.NonScaledSize = skillSize.Pad(skillBlock.Padding).ToPoint();
|
||||||
|
|
||||||
|
skillListBox = new GUIListBox(new RectTransform(new Vector2(1f, 1f - skillBlock.RectTransform.RelativeSize.Y), skillLayout.RectTransform), style: null);
|
||||||
|
CreateTalentSkillList(controlledCharacter, skillListBox);
|
||||||
|
|
||||||
|
if (!TalentTree.JobTalentTrees.TryGetValue(controlledCharacter.Info.Job.Prefab.Identifier, out TalentTree talentTree)) { return; }
|
||||||
|
|
||||||
|
new GUIFrame(new RectTransform(new Vector2(1f, 1f), talentFrameLayoutGroup.RectTransform), style: "HorizontalLine");
|
||||||
|
|
||||||
|
GUIListBox talentTreeListBox = new GUIListBox(new RectTransform(new Vector2(1f, 0.7f), talentFrameLayoutGroup.RectTransform, Anchor.TopCenter), isHorizontal: true, style: null);
|
||||||
|
|
||||||
|
List<GUITextBlock> subTreeNames = new List<GUITextBlock>();
|
||||||
|
foreach (var subTree in talentTree.TalentSubTrees)
|
||||||
|
{
|
||||||
|
GUIFrame subTreeFrame = new GUIFrame(new RectTransform(new Vector2(0.333f, 1f), talentTreeListBox.Content.RectTransform, anchor: Anchor.TopLeft), style: null);
|
||||||
|
GUILayoutGroup subTreeLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1f, 1f), subTreeFrame.RectTransform, Anchor.Center), false, childAnchor: Anchor.TopCenter);
|
||||||
|
|
||||||
|
GUIFrame subtreeTitleFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.111f), subTreeLayoutGroup.RectTransform, anchor: Anchor.TopCenter), style: null);
|
||||||
|
int elementPadding = GUI.IntScale(8);
|
||||||
|
Point headerSize = subtreeTitleFrame.RectTransform.NonScaledSize;
|
||||||
|
GUIFrame subTreeTitleBackground = new GUIFrame(new RectTransform(new Point(headerSize.X - elementPadding, headerSize.Y), subtreeTitleFrame.RectTransform, anchor: Anchor.Center), style: "SubtreeHeader");
|
||||||
|
subTreeNames.Add(new GUITextBlock(new RectTransform(Vector2.One, subTreeTitleBackground.RectTransform, anchor: Anchor.TopCenter), subTree.DisplayName, font: GUI.SubHeadingFont, textAlignment: Alignment.Center));
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
GUIFrame talentOptionFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.222f), subTreeLayoutGroup.RectTransform, anchor: Anchor.TopCenter), style: null);
|
||||||
|
|
||||||
|
Point talentFrameSize = talentOptionFrame.RectTransform.NonScaledSize;
|
||||||
|
|
||||||
|
GUIFrame talentBackground = new GUIFrame(new RectTransform(new Point(talentFrameSize.X - elementPadding, talentFrameSize.Y - elementPadding), talentOptionFrame.RectTransform, anchor: Anchor.Center), style: "TalentBackground");
|
||||||
|
GUIFrame talentBackgroundHighlight = new GUIFrame(new RectTransform(Vector2.One, talentBackground.RectTransform, anchor: Anchor.Center), style: "TalentBackgroundGlow") { Visible = false };
|
||||||
|
|
||||||
|
GUIImage cornerIcon = new GUIImage(new RectTransform(new Vector2(0.2f), talentOptionFrame.RectTransform, anchor: Anchor.BottomRight, scaleBasis: ScaleBasis.BothHeight) { MaxSize = new Point(16) }, style: null)
|
||||||
|
{
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
|
||||||
|
Point iconSize = cornerIcon.RectTransform.NonScaledSize;
|
||||||
|
cornerIcon.RectTransform.AbsoluteOffset = new Point(iconSize.X / 2, iconSize.Y / 2);
|
||||||
|
|
||||||
|
if (subTree.TalentOptionStages.Count > i)
|
||||||
|
{
|
||||||
|
TalentOption talentOption = subTree.TalentOptionStages[i];
|
||||||
|
|
||||||
|
GUILayoutGroup talentOptionCenterGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.75f, 0.7f), talentOptionFrame.RectTransform, Anchor.Center), childAnchor: Anchor.CenterLeft);
|
||||||
|
|
||||||
|
GUILayoutGroup talentOptionLayoutGroup = new GUILayoutGroup(new RectTransform(Vector2.One, talentOptionCenterGroup.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) { Stretch = true };
|
||||||
|
|
||||||
|
foreach (TalentPrefab talent in talentOption.Talents)
|
||||||
|
{
|
||||||
|
GUIFrame talentFrame = new GUIFrame(new RectTransform(Vector2.One, talentOptionLayoutGroup.RectTransform), style: null)
|
||||||
|
{
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
|
||||||
|
GUIFrame croppedTalentFrame = new GUIFrame(new RectTransform(Vector2.One, talentFrame.RectTransform, anchor: Anchor.Center, scaleBasis: ScaleBasis.BothHeight), style: null);
|
||||||
|
|
||||||
|
GUIButton talentButton = new GUIButton(new RectTransform(Vector2.One, croppedTalentFrame.RectTransform, anchor: Anchor.Center), style: null)
|
||||||
|
{
|
||||||
|
ToolTip = $"{talent.DisplayName}\n\n{talent.Description}",
|
||||||
|
UserData = talent.Identifier,
|
||||||
|
PressedColor = pressedColor,
|
||||||
|
OnClicked = (button, userData) =>
|
||||||
|
{
|
||||||
|
// deselect other buttons in tier by removing their selected talents from pool
|
||||||
|
foreach (GUIButton guiButton in talentOptionLayoutGroup.GetAllChildren<GUIButton>())
|
||||||
|
{
|
||||||
|
if (guiButton.UserData is string otherTalentIdentifier && guiButton != button)
|
||||||
|
{
|
||||||
|
if (!controlledCharacter.HasTalent(otherTalentIdentifier))
|
||||||
|
{
|
||||||
|
selectedTalents.Remove(otherTalentIdentifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
string talentIdentifier = userData as string;
|
||||||
|
|
||||||
|
if (TalentTree.IsViableTalentForCharacter(controlledCharacter, talentIdentifier, selectedTalents))
|
||||||
|
{
|
||||||
|
if (!selectedTalents.Contains(talentIdentifier))
|
||||||
|
{
|
||||||
|
selectedTalents.Add(talentIdentifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!controlledCharacter.HasTalent(talentIdentifier))
|
||||||
|
{
|
||||||
|
selectedTalents.Remove(talentIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateTalentButtons();
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
talentButton.Color = talentButton.HoverColor = talentButton.PressedColor = talentButton.SelectedColor = Color.Transparent;
|
||||||
|
|
||||||
|
GUIComponent iconImage;
|
||||||
|
if (talent.Icon is null)
|
||||||
|
{
|
||||||
|
iconImage = new GUITextBlock(new RectTransform(Vector2.One, talentButton.RectTransform, anchor: Anchor.Center), text: "???", font: GUI.LargeFont, textAlignment: Alignment.Center, style: null)
|
||||||
|
{
|
||||||
|
OutlineColor = GUI.Style.Red,
|
||||||
|
TextColor = GUI.Style.Red,
|
||||||
|
PressedColor = unselectableColor,
|
||||||
|
CanBeFocused = false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iconImage = new GUIImage(new RectTransform(Vector2.One, talentButton.RectTransform, anchor: Anchor.Center), sprite: talent.Icon, scaleToFit: true)
|
||||||
|
{
|
||||||
|
PressedColor = unselectableColor,
|
||||||
|
CanBeFocused = false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
talentButtons.Add((talentButton, iconImage));
|
||||||
|
}
|
||||||
|
|
||||||
|
talentCornerIcons.Add((subTree.Identifier, i, cornerIcon, talentBackground, talentBackgroundHighlight));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GUITextBlock.AutoScaleAndNormalize(subTreeNames);
|
||||||
|
|
||||||
|
GUILayoutGroup talentBottomFrame = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.07f), talentFrameLayoutGroup.RectTransform, Anchor.TopCenter), isHorizontal: true) { RelativeSpacing = 0.01f };
|
||||||
|
|
||||||
|
GUILayoutGroup experienceLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.59f, 1f), talentBottomFrame.RectTransform));
|
||||||
|
GUIFrame experienceBarFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.5f), experienceLayout.RectTransform), style: null);
|
||||||
|
|
||||||
|
experienceBar = new GUIProgressBar(new RectTransform(new Vector2(1f, 1f), experienceBarFrame.RectTransform, Anchor.CenterLeft),
|
||||||
|
barSize: controlledCharacter.Info.GetProgressTowardsNextLevel(), color: GUI.Style.Green)
|
||||||
|
{
|
||||||
|
IsHorizontal = true
|
||||||
|
};
|
||||||
|
|
||||||
|
experienceText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), experienceBarFrame.RectTransform, anchor: Anchor.Center), "", font: GUI.Font, textAlignment: Alignment.CenterRight)
|
||||||
|
{
|
||||||
|
Shadow = true
|
||||||
|
};
|
||||||
|
|
||||||
|
talentPointText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), experienceLayout.RectTransform, anchor: Anchor.Center), "", font: GUI.SubHeadingFont, parseRichText: true, textAlignment: Alignment.CenterRight) { AutoScaleVertical = true };
|
||||||
|
|
||||||
|
talentResetButton = new GUIButton(new RectTransform(new Vector2(0.19f, 1f), talentBottomFrame.RectTransform), text: TextManager.Get("reset"), style: "GUIButtonFreeScale")
|
||||||
|
{
|
||||||
|
OnClicked = ResetTalentSelection
|
||||||
|
};
|
||||||
|
talentApplyButton = new GUIButton(new RectTransform(new Vector2(0.19f, 1f), talentBottomFrame.RectTransform), text: TextManager.Get("applysettingsbutton"), style: "GUIButtonFreeScale")
|
||||||
|
{
|
||||||
|
OnClicked = ApplyTalentSelection,
|
||||||
|
};
|
||||||
|
GUITextBlock.AutoScaleAndNormalize(talentResetButton.TextBlock, talentApplyButton.TextBlock);
|
||||||
|
|
||||||
|
UpdateTalentButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateTalentSkillList(Character character, GUIListBox parent)
|
||||||
|
{
|
||||||
|
parent.Content.ClearChildren();
|
||||||
|
List<GUITextBlock> skillNames = new List<GUITextBlock>();
|
||||||
|
foreach (Skill skill in character.Info.Job.Skills)
|
||||||
|
{
|
||||||
|
GUILayoutGroup skillContainer = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.2f), parent.Content.RectTransform), isHorizontal: true) { CanBeFocused = false };
|
||||||
|
|
||||||
|
skillNames.Add(new GUITextBlock(new RectTransform(new Vector2(0.7f, 1f), skillContainer.RectTransform), TextManager.Get($"skillname.{skill.Identifier}", returnNull: true) ?? skill.Identifier));
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), skillContainer.RectTransform), Math.Floor(skill.Level).ToString("F0"), textAlignment: Alignment.CenterRight) { Padding = new Vector4(0, 0, 4, 0) };
|
||||||
|
|
||||||
|
float modifiedSkillLevel = character.GetSkillLevel(skill.Identifier);
|
||||||
|
if (!MathUtils.NearlyEqual(MathF.Floor(modifiedSkillLevel), MathF.Floor(skill.Level)))
|
||||||
|
{
|
||||||
|
int skillChange = (int)MathF.Floor(modifiedSkillLevel - skill.Level);
|
||||||
|
string stringColor = true switch
|
||||||
|
{
|
||||||
|
true when skillChange > 0 => XMLExtensions.ColorToString(GUI.Style.Green),
|
||||||
|
true when skillChange < 0 => XMLExtensions.ColorToString(GUI.Style.Red),
|
||||||
|
_ => XMLExtensions.ColorToString(GUI.Style.TextColor)
|
||||||
|
};
|
||||||
|
|
||||||
|
string changeText = $"(‖color:{stringColor}‖{(skillChange > 0 ? "+" : string.Empty) + skillChange}‖color:end‖)";
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), skillContainer.RectTransform), changeText, parseRichText: true) { Padding = Vector4.Zero };
|
||||||
|
}
|
||||||
|
skillContainer.Recalculate();
|
||||||
|
}
|
||||||
|
|
||||||
|
parent.RecalculateChildren();
|
||||||
|
GUITextBlock.AutoScaleAndNormalize(skillNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateTalentButtons()
|
||||||
|
{
|
||||||
|
Character controlledCharacter = Character.Controlled;
|
||||||
|
|
||||||
|
experienceText.Text = $"{controlledCharacter.Info.ExperiencePoints - controlledCharacter.Info.GetExperienceRequiredForCurrentLevel()} / {controlledCharacter.Info.GetExperienceRequiredToLevelUp() - controlledCharacter.Info.GetExperienceRequiredForCurrentLevel()}";
|
||||||
|
experienceBar.BarSize = controlledCharacter.Info.GetProgressTowardsNextLevel();
|
||||||
|
//experienceBar.ToolTip = $"{controlledCharacter.Info.ExperiencePoints - controlledCharacter.Info.GetExperienceRequiredForCurrentLevel()} / {controlledCharacter.Info.GetExperienceRequiredToLevelUp() - controlledCharacter.Info.GetExperienceRequiredForCurrentLevel()}";
|
||||||
|
|
||||||
|
selectedTalents = TalentTree.CheckTalentSelection(controlledCharacter, selectedTalents);
|
||||||
|
|
||||||
|
string pointsLeft = controlledCharacter.Info.GetAvailableTalentPoints().ToString();
|
||||||
|
|
||||||
|
int talentCount = selectedTalents.Count - controlledCharacter.Info.GetUnlockedTalentsInTree().Count();
|
||||||
|
|
||||||
|
if (talentCount > 0)
|
||||||
|
{
|
||||||
|
string pointsUsed = $"‖color:{XMLExtensions.ColorToString(GUI.Style.Red)}‖{-talentCount}‖color:end‖";
|
||||||
|
string localizedString = TextManager.GetWithVariables("talentmenu.points.spending", new []{ "[amount]", "[used]" }, new []{ pointsLeft, pointsUsed});
|
||||||
|
talentPointText.SetRichText(localizedString);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
talentPointText.SetRichText(TextManager.GetWithVariable("talentmenu.points", "[amount]", pointsLeft));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var (talentTree, index, icon, frame, glow) in talentCornerIcons)
|
||||||
|
{
|
||||||
|
TalentTree.TalentTreeStageState state = TalentTree.GetTalentOptionStageState(controlledCharacter, talentTree, index, selectedTalents);
|
||||||
|
GUIComponentStyle newStyle = talentStageStyles[state];
|
||||||
|
icon.ApplyStyle(newStyle);
|
||||||
|
icon.Color = newStyle.Color;
|
||||||
|
frame.Color = talentStageBackgroundColors[state];
|
||||||
|
glow.Visible = state == TalentTree.TalentTreeStageState.Highlighted;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var talentButton in talentButtons)
|
||||||
|
{
|
||||||
|
string talentIdentifier = talentButton.button.UserData as string;
|
||||||
|
bool unselectable = !TalentTree.IsViableTalentForCharacter(controlledCharacter, talentIdentifier, selectedTalents) || controlledCharacter.HasTalent(talentIdentifier);
|
||||||
|
Color newTalentColor = unselectable ? unselectableColor : unselectedColor;
|
||||||
|
Color hoverColor = Color.White;
|
||||||
|
|
||||||
|
if (controlledCharacter.HasTalent(talentIdentifier))
|
||||||
|
{
|
||||||
|
newTalentColor = GUI.Style.Green;
|
||||||
|
}
|
||||||
|
else if (selectedTalents.Contains(talentIdentifier))
|
||||||
|
{
|
||||||
|
newTalentColor = GUI.Style.Orange;
|
||||||
|
hoverColor = Color.Lerp(GUI.Style.Orange, Color.White, 0.7f);
|
||||||
|
}
|
||||||
|
|
||||||
|
talentButton.icon.Color = newTalentColor;
|
||||||
|
talentButton.icon.HoverColor = hoverColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateTalentSkillList(controlledCharacter, skillListBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyTalents(Character controlledCharacter)
|
||||||
|
{
|
||||||
|
selectedTalents = TalentTree.CheckTalentSelection(controlledCharacter, selectedTalents);
|
||||||
|
foreach (string talent in selectedTalents)
|
||||||
|
{
|
||||||
|
controlledCharacter.GiveTalent(talent);
|
||||||
|
if (GameMain.Client != null)
|
||||||
|
{
|
||||||
|
GameMain.Client.CreateEntityEvent(controlledCharacter, new object[] { NetEntityEvent.Type.UpdateTalents });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UpdateTalentButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ApplyTalentSelection(GUIButton guiButton, object userData)
|
||||||
|
{
|
||||||
|
Character controlledCharacter = Character.Controlled;
|
||||||
|
ApplyTalents(controlledCharacter);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ResetTalentSelection(GUIButton guiButton, object userData)
|
||||||
|
{
|
||||||
|
Character controlledCharacter = Character.Controlled;
|
||||||
|
selectedTalents = controlledCharacter.Info.GetUnlockedTalentsInTree().ToList();
|
||||||
|
UpdateTalentButtons();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnExperienceChanged(Character character)
|
||||||
|
{
|
||||||
|
if (character != Character.Controlled) { return; }
|
||||||
|
UpdateTalentButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly StatTypes[] basicStats = new StatTypes[]
|
||||||
|
{
|
||||||
|
StatTypes.MaximumHealthMultiplier,
|
||||||
|
StatTypes.MovementSpeed,
|
||||||
|
StatTypes.SwimmingSpeed,
|
||||||
|
StatTypes.RepairSpeed,
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly StatTypes[] combatStats = new StatTypes[]
|
||||||
|
{
|
||||||
|
StatTypes.MeleeAttackMultiplier,
|
||||||
|
StatTypes.MeleeAttackSpeed,
|
||||||
|
StatTypes.RangedAttackSpeed,
|
||||||
|
StatTypes.TurretAttackSpeed,
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly StatTypes[] miscStats = new StatTypes[]
|
||||||
|
{
|
||||||
|
StatTypes.ReputationGainMultiplier,
|
||||||
|
StatTypes.MissionMoneyGainMultiplier,
|
||||||
|
StatTypes.ExperienceGainMultiplier,
|
||||||
|
StatTypes.MissionExperienceGainMultiplier,
|
||||||
|
};
|
||||||
|
|
||||||
|
private void CreateCharacterSheet(GUILayoutGroup characterInfoColumn)
|
||||||
|
{
|
||||||
|
Character controlledCharacter = Character.Controlled;
|
||||||
|
|
||||||
|
CreateRow(basicStats);
|
||||||
|
CreateRow(combatStats);
|
||||||
|
CreateRow(miscStats);
|
||||||
|
|
||||||
|
void CreateRow(StatTypes[] statTypes)
|
||||||
|
{
|
||||||
|
GUILayoutGroup characterInfoRow = new GUILayoutGroup(new RectTransform(new Vector2(0.33f, 1.0f), characterInfoColumn.RectTransform, anchor: Anchor.TopLeft), childAnchor: Anchor.TopCenter);
|
||||||
|
foreach (StatTypes statType in statTypes)
|
||||||
|
{
|
||||||
|
ShowStat(statType, characterInfoRow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowStat(StatTypes statType, GUILayoutGroup characterInfoRow)
|
||||||
|
{
|
||||||
|
GUIFrame textInfoFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.33f), characterInfoRow.RectTransform, Anchor.TopCenter), style: null);
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1f, 1f), textInfoFrame.RectTransform, Anchor.TopLeft), statType.ToString(), font: GUI.SmallFont, textAlignment: Alignment.TopLeft);
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1f, 1f), textInfoFrame.RectTransform, Anchor.TopLeft), (int)(100f * (1 + controlledCharacter.GetStatValue(statType))) + "%", font: GUI.Font, textAlignment: Alignment.TopRight);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,8 +115,9 @@ namespace Barotrauma
|
|||||||
return MathHelper.Clamp(Math.Min(Math.Min(scale.X, scale.Y), GUI.SlicedSpriteScale), minBorderScale, maxBorderScale);
|
return MathHelper.Clamp(Math.Min(Math.Min(scale.X, scale.Y), GUI.SlicedSpriteScale), minBorderScale, maxBorderScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Draw(SpriteBatch spriteBatch, Rectangle rect, Color color, SpriteEffects spriteEffects = SpriteEffects.None)
|
public void Draw(SpriteBatch spriteBatch, Rectangle rect, Color color, SpriteEffects spriteEffects = SpriteEffects.None, Vector2? uvOffset = null)
|
||||||
{
|
{
|
||||||
|
uvOffset ??= Vector2.Zero;
|
||||||
if (Sprite.Texture == null)
|
if (Sprite.Texture == null)
|
||||||
{
|
{
|
||||||
GUI.DrawRectangle(spriteBatch, rect, Color.Magenta);
|
GUI.DrawRectangle(spriteBatch, rect, Color.Magenta);
|
||||||
@@ -157,7 +158,7 @@ namespace Barotrauma
|
|||||||
else if (Tile)
|
else if (Tile)
|
||||||
{
|
{
|
||||||
Vector2 startPos = new Vector2(rect.X, rect.Y);
|
Vector2 startPos = new Vector2(rect.X, rect.Y);
|
||||||
Sprite.DrawTiled(spriteBatch, startPos, new Vector2(rect.Width, rect.Height), color);
|
Sprite.DrawTiled(spriteBatch, startPos, new Vector2(rect.Width, rect.Height), color, startOffset: uvOffset);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1045,10 +1045,10 @@ namespace Barotrauma
|
|||||||
public static GUIFrame CreateUpgradeFrame(UpgradePrefab prefab, UpgradeCategory category, CampaignMode campaign, RectTransform rectTransform, bool addBuyButton = true)
|
public static GUIFrame CreateUpgradeFrame(UpgradePrefab prefab, UpgradeCategory category, CampaignMode campaign, RectTransform rectTransform, bool addBuyButton = true)
|
||||||
{
|
{
|
||||||
int price = prefab.Price.GetBuyprice(campaign.UpgradeManager.GetUpgradeLevel(prefab, category), campaign.Map?.CurrentLocation);
|
int price = prefab.Price.GetBuyprice(campaign.UpgradeManager.GetUpgradeLevel(prefab, category), campaign.Map?.CurrentLocation);
|
||||||
return CreateUpgradeEntry(rectTransform, prefab.Sprite, prefab.Name, prefab.Description, price, new CategoryData(category, prefab), addBuyButton);
|
return CreateUpgradeEntry(rectTransform, prefab.Sprite, prefab.Name, prefab.Description, price, new CategoryData(category, prefab), addBuyButton, upgradePrefab: prefab, currentLevel: campaign.UpgradeManager.GetUpgradeLevel(prefab, category));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GUIFrame CreateUpgradeEntry(RectTransform parent, Sprite sprite, string title, string body, int price, object? userData, bool addBuyButton = true, bool addProgressBar = true, string buttonStyle = "UpgradeBuyButton")
|
public static GUIFrame CreateUpgradeEntry(RectTransform parent, Sprite sprite, string title, string body, int price, object? userData, bool addBuyButton = true, bool addProgressBar = true, string buttonStyle = "UpgradeBuyButton", UpgradePrefab upgradePrefab = null, int currentLevel = 0)
|
||||||
{
|
{
|
||||||
float progressBarHeight = 0.25f;
|
float progressBarHeight = 0.25f;
|
||||||
|
|
||||||
@@ -1089,7 +1089,7 @@ namespace Barotrauma
|
|||||||
//negative price = refund
|
//negative price = refund
|
||||||
if (price < 0) { formattedPrice = "+" + formattedPrice; }
|
if (price < 0) { formattedPrice = "+" + formattedPrice; }
|
||||||
buyButtonLayout = new GUILayoutGroup(rectT(0.2f, 1, prefabLayout), childAnchor: Anchor.TopCenter) { UserData = "buybutton" };
|
buyButtonLayout = new GUILayoutGroup(rectT(0.2f, 1, prefabLayout), childAnchor: Anchor.TopCenter) { UserData = "buybutton" };
|
||||||
var priceText = new GUITextBlock(rectT(1, 0.4f, buyButtonLayout), formattedPrice, textAlignment: Alignment.Center);
|
var priceText = new GUITextBlock(rectT(1, 0.2f, buyButtonLayout), formattedPrice, textAlignment: Alignment.Center);
|
||||||
if (price < 0)
|
if (price < 0)
|
||||||
{
|
{
|
||||||
priceText.TextColor = GUI.Style.Green;
|
priceText.TextColor = GUI.Style.Green;
|
||||||
@@ -1099,6 +1099,11 @@ namespace Barotrauma
|
|||||||
priceText.Text = string.Empty;
|
priceText.Text = string.Empty;
|
||||||
}
|
}
|
||||||
new GUIButton(rectT(0.7f, 0.5f, buyButtonLayout), string.Empty, style: buttonStyle) { Enabled = false };
|
new GUIButton(rectT(0.7f, 0.5f, buyButtonLayout), string.Empty, style: buttonStyle) { Enabled = false };
|
||||||
|
if (upgradePrefab != null)
|
||||||
|
{
|
||||||
|
var increaseText = new GUITextBlock(rectT(1, 0.2f, buyButtonLayout), "", textAlignment: Alignment.Center);
|
||||||
|
UpdateUpgradePercentageText(increaseText, upgradePrefab, currentLevel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
description.CalculateHeightFromText();
|
description.CalculateHeightFromText();
|
||||||
@@ -1127,6 +1132,19 @@ namespace Barotrauma
|
|||||||
return prefabFrame;
|
return prefabFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void UpdateUpgradePercentageText(GUITextBlock text, UpgradePrefab upgradePrefab, int currentLevel)
|
||||||
|
{
|
||||||
|
float nextIncrease = upgradePrefab.IncreaseOnTooltip * (Math.Min(currentLevel + 1, upgradePrefab.MaxLevel));
|
||||||
|
if (nextIncrease != 0f)
|
||||||
|
{
|
||||||
|
text.Text = $"{Math.Round(nextIncrease, 1)} %";
|
||||||
|
if (currentLevel == upgradePrefab.MaxLevel)
|
||||||
|
{
|
||||||
|
text.TextColor = Color.Gray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void CreateUpgradeEntry(UpgradePrefab prefab, UpgradeCategory category, GUIComponent parent, List<Item>? itemsOnSubmarine)
|
private void CreateUpgradeEntry(UpgradePrefab prefab, UpgradeCategory category, GUIComponent parent, List<Item>? itemsOnSubmarine)
|
||||||
{
|
{
|
||||||
if (Campaign is null) { return; }
|
if (Campaign is null) { return; }
|
||||||
@@ -1541,7 +1559,9 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (prefabFrame.FindChild("buybutton", true) is { } buttonParent)
|
if (prefabFrame.FindChild("buybutton", true) is { } buttonParent)
|
||||||
{
|
{
|
||||||
GUITextBlock priceLabel = buttonParent.GetChild<GUITextBlock>();
|
List<GUITextBlock> textBlocks = buttonParent.GetAllChildren<GUITextBlock>().ToList();
|
||||||
|
|
||||||
|
GUITextBlock priceLabel = textBlocks[0];
|
||||||
int price = prefab.Price.GetBuyprice(campaign.UpgradeManager.GetUpgradeLevel(prefab, category), campaign.Map?.CurrentLocation);
|
int price = prefab.Price.GetBuyprice(campaign.UpgradeManager.GetUpgradeLevel(prefab, category), campaign.Map?.CurrentLocation);
|
||||||
|
|
||||||
if (priceLabel != null && !WaitForServerUpdate)
|
if (priceLabel != null && !WaitForServerUpdate)
|
||||||
@@ -1562,6 +1582,11 @@ namespace Barotrauma
|
|||||||
button.Enabled = false;
|
button.Enabled = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
GUITextBlock increaseLabel = textBlocks[1];
|
||||||
|
if (increaseLabel != null && !WaitForServerUpdate)
|
||||||
|
{
|
||||||
|
UpdateUpgradePercentageText(increaseLabel, prefab, currentLevel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ namespace Barotrauma
|
|||||||
public static SteamWorkshopScreen SteamWorkshopScreen;
|
public static SteamWorkshopScreen SteamWorkshopScreen;
|
||||||
|
|
||||||
public static SubEditorScreen SubEditorScreen;
|
public static SubEditorScreen SubEditorScreen;
|
||||||
|
public static TestScreen TestScreen;
|
||||||
public static ParticleEditorScreen ParticleEditorScreen;
|
public static ParticleEditorScreen ParticleEditorScreen;
|
||||||
public static LevelEditorScreen LevelEditorScreen;
|
public static LevelEditorScreen LevelEditorScreen;
|
||||||
public static SpriteEditorScreen SpriteEditorScreen;
|
public static SpriteEditorScreen SpriteEditorScreen;
|
||||||
@@ -89,7 +90,16 @@ namespace Barotrauma
|
|||||||
public static ParticleManager ParticleManager;
|
public static ParticleManager ParticleManager;
|
||||||
public static DecalManager DecalManager;
|
public static DecalManager DecalManager;
|
||||||
|
|
||||||
public static World World;
|
private static World world;
|
||||||
|
public static World World
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (world == null) { world = new World(new Vector2(0, -9.82f)); }
|
||||||
|
return world;
|
||||||
|
}
|
||||||
|
set { world = value; }
|
||||||
|
}
|
||||||
|
|
||||||
public static LoadingScreen TitleScreen;
|
public static LoadingScreen TitleScreen;
|
||||||
private bool loadingScreenOpen;
|
private bool loadingScreenOpen;
|
||||||
@@ -184,6 +194,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
public static bool FirstLoad = true;
|
public static bool FirstLoad = true;
|
||||||
|
|
||||||
|
public static bool CancelQuickStart;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public GameMain(string[] args)
|
public GameMain(string[] args)
|
||||||
@@ -239,7 +251,6 @@ namespace Barotrauma
|
|||||||
GameMain.ResetFrameTime();
|
GameMain.ResetFrameTime();
|
||||||
fixedTime = new GameTime();
|
fixedTime = new GameTime();
|
||||||
|
|
||||||
World = new World(new Vector2(0, -9.82f));
|
|
||||||
FarseerPhysics.Settings.AllowSleep = true;
|
FarseerPhysics.Settings.AllowSleep = true;
|
||||||
FarseerPhysics.Settings.ContinuousPhysics = false;
|
FarseerPhysics.Settings.ContinuousPhysics = false;
|
||||||
FarseerPhysics.Settings.VelocityIterations = 1;
|
FarseerPhysics.Settings.VelocityIterations = 1;
|
||||||
@@ -567,6 +578,8 @@ namespace Barotrauma
|
|||||||
ItemPrefab.LoadAll(GetFilesOfType(ContentType.Item));
|
ItemPrefab.LoadAll(GetFilesOfType(ContentType.Item));
|
||||||
AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions));
|
AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions));
|
||||||
SkillSettings.Load(GetFilesOfType(ContentType.SkillSettings));
|
SkillSettings.Load(GetFilesOfType(ContentType.SkillSettings));
|
||||||
|
TalentPrefab.LoadAll(GetFilesOfType(ContentType.Talents));
|
||||||
|
TalentTree.LoadAll(GetFilesOfType(ContentType.TalentTrees));
|
||||||
Order.Init();
|
Order.Init();
|
||||||
EventManagerSettings.Init();
|
EventManagerSettings.Init();
|
||||||
BallastFloraPrefab.LoadAll(GetFilesOfType(ContentType.MapCreature));
|
BallastFloraPrefab.LoadAll(GetFilesOfType(ContentType.MapCreature));
|
||||||
@@ -620,6 +633,7 @@ namespace Barotrauma
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
SubEditorScreen = new SubEditorScreen();
|
SubEditorScreen = new SubEditorScreen();
|
||||||
|
TestScreen = new TestScreen();
|
||||||
|
|
||||||
TitleScreen.LoadState = 75.0f;
|
TitleScreen.LoadState = 75.0f;
|
||||||
yield return CoroutineStatus.Running;
|
yield return CoroutineStatus.Running;
|
||||||
@@ -792,12 +806,18 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
if (TitleScreen.LoadState >= 100.0f && !TitleScreen.PlayingSplashScreen && (Config.AutomaticQuickStartEnabled || Config.AutomaticCampaignLoadEnabled) && FirstLoad && !PlayerInput.KeyDown(Keys.LeftShift))
|
CancelQuickStart |= PlayerInput.KeyDown(Keys.LeftShift);
|
||||||
|
|
||||||
|
if (TitleScreen.LoadState >= 100.0f && !TitleScreen.PlayingSplashScreen && (Config.AutomaticQuickStartEnabled || Config.AutomaticCampaignLoadEnabled || Config.TestScreenEnabled) && FirstLoad && !CancelQuickStart)
|
||||||
{
|
{
|
||||||
loadingScreenOpen = false;
|
loadingScreenOpen = false;
|
||||||
FirstLoad = false;
|
FirstLoad = false;
|
||||||
|
|
||||||
if (Config.AutomaticQuickStartEnabled)
|
if (Config.TestScreenEnabled)
|
||||||
|
{
|
||||||
|
TestScreen.Select();
|
||||||
|
}
|
||||||
|
else if (Config.AutomaticQuickStartEnabled)
|
||||||
{
|
{
|
||||||
MainMenuScreen.QuickStart();
|
MainMenuScreen.QuickStart();
|
||||||
}
|
}
|
||||||
@@ -902,8 +922,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
//open the pause menu if not controlling a character OR if the character has no UIs active that can be closed with ESC
|
//open the pause menu if not controlling a character OR if the character has no UIs active that can be closed with ESC
|
||||||
else if ((Character.Controlled == null || !itemHudActive())
|
else if ((Character.Controlled == null || !itemHudActive())
|
||||||
//TODO: do we need to check Inventory.SelectedSlot?
|
&& CharacterHealth.OpenHealthWindow == null
|
||||||
&& Inventory.SelectedSlot == null && CharacterHealth.OpenHealthWindow == null
|
|
||||||
&& !CrewManager.IsCommandInterfaceOpen
|
&& !CrewManager.IsCommandInterfaceOpen
|
||||||
&& !(Screen.Selected is SubEditorScreen editor && !editor.WiringMode && Character.Controlled?.SelectedConstruction != null))
|
&& !(Screen.Selected is SubEditorScreen editor && !editor.WiringMode && Character.Controlled?.SelectedConstruction != null))
|
||||||
{
|
{
|
||||||
@@ -1048,7 +1067,6 @@ namespace Barotrauma
|
|||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sw.Stop();
|
sw.Stop();
|
||||||
PerformanceCounter.AddElapsedTicks("Draw total", sw.ElapsedTicks);
|
PerformanceCounter.AddElapsedTicks("Draw total", sw.ElapsedTicks);
|
||||||
PerformanceCounter.DrawTimeGraph.Update(sw.ElapsedTicks * 1000.0f / (float)Stopwatch.Frequency);
|
PerformanceCounter.DrawTimeGraph.Update(sw.ElapsedTicks * 1000.0f / (float)Stopwatch.Frequency);
|
||||||
|
|||||||
@@ -48,11 +48,7 @@ namespace Barotrauma
|
|||||||
var equipmentSlots = new List<InvSlotType>() { InvSlotType.Head, InvSlotType.InnerClothes, InvSlotType.OuterClothes, InvSlotType.Headset, InvSlotType.Card };
|
var equipmentSlots = new List<InvSlotType>() { InvSlotType.Head, InvSlotType.InnerClothes, InvSlotType.OuterClothes, InvSlotType.Headset, InvSlotType.Card };
|
||||||
return character.Inventory.FindAllItems(item =>
|
return character.Inventory.FindAllItems(item =>
|
||||||
{
|
{
|
||||||
if (item.SpawnedInOutpost) { return false; }
|
if (!IsItemSellable(item, confirmedSoldEntities)) { return false; }
|
||||||
if (!item.Prefab.AllowSellingWhenBroken && item.ConditionPercentage < 90.0f) { return false; }
|
|
||||||
if (confirmedSoldEntities.Any(it => it.Item == item)) { return false; }
|
|
||||||
// There must be no contained items or the contained items must be confirmed as sold
|
|
||||||
if (!item.ContainedItems.All(it => confirmedSoldEntities.Any(se => se.Item == it))) { return false; }
|
|
||||||
// Item must be in a non-equipment slot if possible
|
// Item must be in a non-equipment slot if possible
|
||||||
if (!item.AllowedSlots.All(s => equipmentSlots.Contains(s)) && IsInEquipmentSlot(item)) { return false; }
|
if (!item.AllowedSlots.All(s => equipmentSlots.Contains(s)) && IsInEquipmentSlot(item)) { return false; }
|
||||||
// Item must not be contained inside an item in an equipment slot
|
// Item must not be contained inside an item in an equipment slot
|
||||||
@@ -76,15 +72,10 @@ namespace Barotrauma
|
|||||||
var confirmedSoldEntities = GetConfirmedSoldEntities();
|
var confirmedSoldEntities = GetConfirmedSoldEntities();
|
||||||
return Submarine.MainSub.GetItems(true).FindAll(item =>
|
return Submarine.MainSub.GetItems(true).FindAll(item =>
|
||||||
{
|
{
|
||||||
if (!item.Prefab.CanBeSold) { return false; }
|
if (!IsItemSellable(item, confirmedSoldEntities)) { return false; }
|
||||||
if (item.SpawnedInOutpost) { return false; }
|
|
||||||
if (!item.Prefab.AllowSellingWhenBroken && item.ConditionPercentage < 90.0f) { return false; }
|
|
||||||
if (!item.Components.All(c => !(c is Holdable h) || !h.Attachable || !h.Attached)) { return false; }
|
if (!item.Components.All(c => !(c is Holdable h) || !h.Attachable || !h.Attached)) { return false; }
|
||||||
if (!item.Components.All(c => !(c is Wire w) || w.Connections.All(c => c == null))) { return false; }
|
if (!item.Components.All(c => !(c is Wire w) || w.Connections.All(c => c == null))) { return false; }
|
||||||
if (!ItemAndAllContainersInteractable(item)) { return false; }
|
if (!ItemAndAllContainersInteractable(item)) { return false; }
|
||||||
if (confirmedSoldEntities.Any(it => it.Item == item)) { return false; }
|
|
||||||
// There must be no contained items or the contained items must be confirmed as sold
|
|
||||||
if (!item.ContainedItems.All(it => confirmedSoldEntities.Any(se => se.Item == it))) { return false; }
|
|
||||||
return true;
|
return true;
|
||||||
}).Distinct();
|
}).Distinct();
|
||||||
|
|
||||||
@@ -107,6 +98,24 @@ namespace Barotrauma
|
|||||||
return SoldEntities.Where(se => se.Status != SoldEntity.SellStatus.Unconfirmed);
|
return SoldEntities.Where(se => se.Status != SoldEntity.SellStatus.Unconfirmed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsItemSellable(Item item, IEnumerable<SoldEntity> confirmedSoldEntities)
|
||||||
|
{
|
||||||
|
if (!item.Prefab.CanBeSold) { return false; }
|
||||||
|
if (item.SpawnedInOutpost) { return false; }
|
||||||
|
if (!item.Prefab.AllowSellingWhenBroken && item.ConditionPercentage < 90.0f) { return false; }
|
||||||
|
if (confirmedSoldEntities.Any(it => it.Item == item)) { return false; }
|
||||||
|
if (item.OwnInventory?.Container is ItemContainer itemContainer)
|
||||||
|
{
|
||||||
|
var containedItems = item.ContainedItems;
|
||||||
|
if (containedItems.None()) { return true; }
|
||||||
|
// Allow selling the item if contained items are unsellable and set to be removed on deconstruct
|
||||||
|
if (itemContainer.RemoveContainedItemsOnDeconstruct && containedItems.All(it => !it.Prefab.CanBeSold)) { return true; }
|
||||||
|
// Otherwise there must be no contained items or the contained items must be confirmed as sold
|
||||||
|
if (!containedItems.All(it => confirmedSoldEntities.Any(se => se.Item == it))) { return false; }
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public void SetItemsInBuyCrate(List<PurchasedItem> items)
|
public void SetItemsInBuyCrate(List<PurchasedItem> items)
|
||||||
{
|
{
|
||||||
ItemsInBuyCrate.Clear();
|
ItemsInBuyCrate.Clear();
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+3
-3
@@ -60,7 +60,7 @@ namespace Barotrauma
|
|||||||
var newCampaignContainer = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.95f), campaignContainer.RectTransform, Anchor.Center), style: null);
|
var newCampaignContainer = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.95f), campaignContainer.RectTransform, Anchor.Center), style: null);
|
||||||
var loadCampaignContainer = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.95f), campaignContainer.RectTransform, Anchor.Center), style: null);
|
var loadCampaignContainer = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.95f), campaignContainer.RectTransform, Anchor.Center), style: null);
|
||||||
|
|
||||||
GameMain.NetLobbyScreen.CampaignSetupUI = new CampaignSetupUI(true, newCampaignContainer, loadCampaignContainer, null, saveFiles);
|
GameMain.NetLobbyScreen.CampaignSetupUI = new MultiPlayerCampaignSetupUI(newCampaignContainer, loadCampaignContainer, null, saveFiles);
|
||||||
|
|
||||||
var newCampaignButton = new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), buttonContainer.RectTransform),
|
var newCampaignButton = new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), buttonContainer.RectTransform),
|
||||||
TextManager.Get("NewCampaign"), style: "GUITabButton")
|
TextManager.Get("NewCampaign"), style: "GUITabButton")
|
||||||
@@ -761,7 +761,7 @@ namespace Barotrauma
|
|||||||
Faction faction = campaign.Factions.FirstOrDefault(f => f.Prefab.Identifier.Equals(identifier, StringComparison.OrdinalIgnoreCase));
|
Faction faction = campaign.Factions.FirstOrDefault(f => f.Prefab.Identifier.Equals(identifier, StringComparison.OrdinalIgnoreCase));
|
||||||
if (faction?.Reputation != null)
|
if (faction?.Reputation != null)
|
||||||
{
|
{
|
||||||
faction.Reputation.Value = rep;
|
faction.Reputation.SetReputation(rep);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -771,7 +771,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (reputation.HasValue)
|
if (reputation.HasValue)
|
||||||
{
|
{
|
||||||
campaign.Map.CurrentLocation.Reputation.Value = reputation.Value;
|
campaign.Map.CurrentLocation.Reputation.SetReputation(reputation.Value);
|
||||||
campaign?.CampaignUI?.UpgradeStore?.RefreshAll();
|
campaign?.CampaignUI?.UpgradeStore?.RefreshAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,10 +21,11 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (GameMain.NetworkMember != null && GameMain.NetLobbyScreen != null)
|
if (GameMain.NetworkMember != null && GameMain.NetLobbyScreen != null)
|
||||||
{
|
{
|
||||||
if (GameMain.NetLobbyScreen.HeadSelectionList != null) { GameMain.NetLobbyScreen.HeadSelectionList.Visible = false; }
|
GameMain.NetLobbyScreen.CharacterAppearanceCustomizationMenu?.Dispose();
|
||||||
|
GameMain.NetLobbyScreen.CharacterAppearanceCustomizationMenu = null;
|
||||||
if (GameMain.NetLobbyScreen.JobSelectionFrame != null) { GameMain.NetLobbyScreen.JobSelectionFrame.Visible = false; }
|
if (GameMain.NetLobbyScreen.JobSelectionFrame != null) { GameMain.NetLobbyScreen.JobSelectionFrame.Visible = false; }
|
||||||
}
|
}
|
||||||
if (tabMenu == null && GameMode is TutorialMode == false)
|
if (tabMenu == null && !(GameMode is TutorialMode) && !ConversationAction.IsDialogOpen)
|
||||||
{
|
{
|
||||||
tabMenu = new TabMenu();
|
tabMenu = new TabMenu();
|
||||||
HintManager.OnShowTabMenu();
|
HintManager.OnShowTabMenu();
|
||||||
@@ -34,17 +35,17 @@ namespace Barotrauma
|
|||||||
tabMenu = null;
|
tabMenu = null;
|
||||||
NetLobbyScreen.JobInfoFrame = null;
|
NetLobbyScreen.JobInfoFrame = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private GUILayoutGroup topLeftButtonGroup;
|
private GUILayoutGroup topLeftButtonGroup;
|
||||||
private GUIButton crewListButton, commandButton, tabMenuButton;
|
private GUIButton crewListButton, commandButton, tabMenuButton;
|
||||||
|
private GUIImage talentPointNotification;
|
||||||
|
|
||||||
private GUIComponent respawnInfoFrame, respawnButtonContainer;
|
private GUIComponent respawnInfoFrame, respawnButtonContainer;
|
||||||
private GUITextBlock respawnInfoText;
|
private GUITextBlock respawnInfoText;
|
||||||
private GUITickBox respawnTickBox;
|
private GUITickBox respawnTickBox;
|
||||||
private GUILayoutGroup TopLeftButtonGroup;
|
|
||||||
private void CreateTopLeftButtons()
|
private void CreateTopLeftButtons()
|
||||||
{
|
{
|
||||||
if (topLeftButtonGroup != null)
|
if (topLeftButtonGroup != null)
|
||||||
@@ -89,11 +90,11 @@ namespace Barotrauma
|
|||||||
tabMenuButton = new GUIButton(new RectTransform(buttonSize, parent: topLeftButtonGroup.RectTransform), style: "TabMenuButton")
|
tabMenuButton = new GUIButton(new RectTransform(buttonSize, parent: topLeftButtonGroup.RectTransform), style: "TabMenuButton")
|
||||||
{
|
{
|
||||||
ToolTip = TextManager.GetWithVariable("hudbutton.tabmenu", "[key]", GameMain.Config.KeyBindText(InputType.InfoTab)),
|
ToolTip = TextManager.GetWithVariable("hudbutton.tabmenu", "[key]", GameMain.Config.KeyBindText(InputType.InfoTab)),
|
||||||
OnClicked = (button, userData) =>
|
OnClicked = (button, userData) => ToggleTabMenu()
|
||||||
{
|
|
||||||
return ToggleTabMenu();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
talentPointNotification = CreateTalentIconNotification(tabMenuButton);
|
||||||
|
|
||||||
GameMain.Instance.ResolutionChanged += CreateTopLeftButtons;
|
GameMain.Instance.ResolutionChanged += CreateTopLeftButtons;
|
||||||
|
|
||||||
respawnInfoFrame = new GUIFrame(new RectTransform(new Vector2(0.5f, 1.0f), parent: topLeftButtonGroup.RectTransform)
|
respawnInfoFrame = new GUIFrame(new RectTransform(new Vector2(0.5f, 1.0f), parent: topLeftButtonGroup.RectTransform)
|
||||||
@@ -140,11 +141,41 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (GameMain.NetworkMember != null)
|
if (GameMain.NetworkMember != null)
|
||||||
{
|
{
|
||||||
GameMain.NetLobbyScreen?.HeadSelectionList?.AddToGUIUpdateList();
|
GameMain.NetLobbyScreen.CharacterAppearanceCustomizationMenu?.AddToGUIUpdateList();
|
||||||
GameMain.NetLobbyScreen?.JobSelectionFrame?.AddToGUIUpdateList();
|
GameMain.NetLobbyScreen?.JobSelectionFrame?.AddToGUIUpdateList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static GUIImage CreateTalentIconNotification(GUIComponent parent, bool offset = true)
|
||||||
|
{
|
||||||
|
GUIImage indicator = new GUIImage(new RectTransform(new Vector2(0.45f), parent.RectTransform, anchor: Anchor.TopRight, scaleBasis: ScaleBasis.BothWidth), style: "TalentPointNotification")
|
||||||
|
{
|
||||||
|
Visible = false,
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
Point notificationSize = indicator.RectTransform.NonScaledSize;
|
||||||
|
if (offset)
|
||||||
|
{
|
||||||
|
indicator.RectTransform.AbsoluteOffset = new Point(-(notificationSize.X / 2), -(notificationSize.Y / 2));
|
||||||
|
}
|
||||||
|
return indicator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void UpdateTalentNotificationIndicator(GUIImage indicator)
|
||||||
|
{
|
||||||
|
if (indicator != null)
|
||||||
|
{
|
||||||
|
if (Character.Controlled?.Info == null)
|
||||||
|
{
|
||||||
|
indicator.Visible = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
indicator.Visible = Character.Controlled.Info.GetAvailableTalentPoints() > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
partial void UpdateProjSpecific(float deltaTime)
|
partial void UpdateProjSpecific(float deltaTime)
|
||||||
{
|
{
|
||||||
if (GUI.DisableHUD) { return; }
|
if (GUI.DisableHUD) { return; }
|
||||||
@@ -166,21 +197,17 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateTalentNotificationIndicator(talentPointNotification);
|
||||||
|
|
||||||
if (GameMain.NetworkMember != null)
|
if (GameMain.NetworkMember != null)
|
||||||
{
|
{
|
||||||
if (GameMain.NetLobbyScreen?.HeadSelectionList != null)
|
GameMain.NetLobbyScreen?.CharacterAppearanceCustomizationMenu?.Update();
|
||||||
{
|
|
||||||
if (PlayerInput.PrimaryMouseButtonDown() && !GUI.IsMouseOn(GameMain.NetLobbyScreen.HeadSelectionList))
|
|
||||||
{
|
|
||||||
if (GameMain.NetLobbyScreen.HeadSelectionList != null) { GameMain.NetLobbyScreen.HeadSelectionList.Visible = false; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (GameMain.NetLobbyScreen?.JobSelectionFrame != null)
|
if (GameMain.NetLobbyScreen?.JobSelectionFrame != null)
|
||||||
{
|
{
|
||||||
if (PlayerInput.PrimaryMouseButtonDown() && !GUI.IsMouseOn(GameMain.NetLobbyScreen.JobSelectionFrame))
|
if (GameMain.NetLobbyScreen.JobSelectionFrame != null && PlayerInput.PrimaryMouseButtonDown() && !GUI.IsMouseOn(GameMain.NetLobbyScreen.JobSelectionFrame))
|
||||||
{
|
{
|
||||||
GameMain.NetLobbyScreen.JobList.Deselect();
|
GameMain.NetLobbyScreen.JobList.Deselect();
|
||||||
if (GameMain.NetLobbyScreen.JobSelectionFrame != null) { GameMain.NetLobbyScreen.JobSelectionFrame.Visible = false; }
|
GameMain.NetLobbyScreen.JobSelectionFrame.Visible = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -544,7 +544,7 @@ namespace Barotrauma
|
|||||||
if (Character.Controlled.CurrentHull == null) { return; }
|
if (Character.Controlled.CurrentHull == null) { return; }
|
||||||
if (HumanAIController.IsBallastFloraNoticeable(Character.Controlled, Character.Controlled.CurrentHull))
|
if (HumanAIController.IsBallastFloraNoticeable(Character.Controlled, Character.Controlled.CurrentHull))
|
||||||
{
|
{
|
||||||
if (DisplayHint("onballastflorainfected")) { return; }
|
if (IsOnFriendlySub() && DisplayHint("onballastflorainfected")) { return; }
|
||||||
}
|
}
|
||||||
foreach (var gap in Character.Controlled.CurrentHull.ConnectedGaps)
|
foreach (var gap in Character.Controlled.CurrentHull.ConnectedGaps)
|
||||||
{
|
{
|
||||||
@@ -552,7 +552,7 @@ namespace Barotrauma
|
|||||||
if (Vector2.DistanceSquared(Character.Controlled.WorldPosition, gap.ConnectedDoor.Item.WorldPosition) > 400 * 400) { continue; }
|
if (Vector2.DistanceSquared(Character.Controlled.WorldPosition, gap.ConnectedDoor.Item.WorldPosition) > 400 * 400) { continue; }
|
||||||
if (!gap.IsRoomToRoom)
|
if (!gap.IsRoomToRoom)
|
||||||
{
|
{
|
||||||
if (!(Character.Controlled.GetEquippedItem("deepdiving", InvSlotType.OuterClothes) is Item)) { continue; }
|
if (!IsWearingDivingSuit()) { continue; }
|
||||||
if (Character.Controlled.IsProtectedFromPressure()) { continue; }
|
if (Character.Controlled.IsProtectedFromPressure()) { continue; }
|
||||||
if (DisplayHint("divingsuitwarning", extendTextTag: false)) { return; }
|
if (DisplayHint("divingsuitwarning", extendTextTag: false)) { return; }
|
||||||
continue;
|
continue;
|
||||||
@@ -561,10 +561,16 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (me == Character.Controlled.CurrentHull) { continue; }
|
if (me == Character.Controlled.CurrentHull) { continue; }
|
||||||
if (!(me is Hull adjacentHull)) { continue; }
|
if (!(me is Hull adjacentHull)) { continue; }
|
||||||
|
if (!IsOnFriendlySub()) { continue; }
|
||||||
|
if (IsWearingDivingSuit()) { continue; }
|
||||||
if (adjacentHull.LethalPressure > 5.0f && DisplayHint("onadjacenthull.highpressure")) { return; }
|
if (adjacentHull.LethalPressure > 5.0f && DisplayHint("onadjacenthull.highpressure")) { return; }
|
||||||
if (adjacentHull.WaterPercentage > 75 && !BallastHulls.Contains(adjacentHull) && DisplayHint("onadjacenthull.highwaterpercentage")) { return; }
|
if (adjacentHull.WaterPercentage > 75 && !BallastHulls.Contains(adjacentHull) && DisplayHint("onadjacenthull.highwaterpercentage")) { return; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool IsWearingDivingSuit() => Character.Controlled.GetEquippedItem("deepdiving", InvSlotType.OuterClothes) is Item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool IsOnFriendlySub() => Character.Controlled.Submarine is Submarine sub && (sub.TeamID == Character.Controlled.TeamID || sub.TeamID == CharacterTeamType.FriendlyNPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CheckReminders()
|
private static void CheckReminders()
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
keyMapping = new KeyOrMouse[Enum.GetNames(typeof(InputType)).Length];
|
keyMapping = new KeyOrMouse[Enum.GetNames(typeof(InputType)).Length];
|
||||||
keyMapping[(int)InputType.Run] = new KeyOrMouse(Keys.LeftShift);
|
keyMapping[(int)InputType.Run] = new KeyOrMouse(Keys.LeftShift);
|
||||||
keyMapping[(int)InputType.Attack] = new KeyOrMouse(Keys.R);
|
keyMapping[(int)InputType.Attack] = new KeyOrMouse(Keys.F);
|
||||||
keyMapping[(int)InputType.Crouch] = new KeyOrMouse(Keys.LeftControl);
|
keyMapping[(int)InputType.Crouch] = new KeyOrMouse(Keys.LeftControl);
|
||||||
keyMapping[(int)InputType.Grab] = new KeyOrMouse(Keys.G);
|
keyMapping[(int)InputType.Grab] = new KeyOrMouse(Keys.G);
|
||||||
keyMapping[(int)InputType.Health] = new KeyOrMouse(Keys.H);
|
keyMapping[(int)InputType.Health] = new KeyOrMouse(Keys.H);
|
||||||
@@ -173,7 +173,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadKeyBinds(XElement element)
|
private void LoadKeyBinds(XElement element, Version gameVersion)
|
||||||
{
|
{
|
||||||
foreach (XAttribute attribute in element.Attributes())
|
foreach (XAttribute attribute in element.Attributes())
|
||||||
{
|
{
|
||||||
@@ -183,7 +183,6 @@ namespace Barotrauma
|
|||||||
keyMapping[(int)InputType.TakeHalfFromInventorySlot] = new KeyOrMouse(Keys.LeftShift);
|
keyMapping[(int)InputType.TakeHalfFromInventorySlot] = new KeyOrMouse(Keys.LeftShift);
|
||||||
keyMapping[(int)InputType.TakeOneFromInventorySlot] = new KeyOrMouse(Keys.LeftControl);
|
keyMapping[(int)InputType.TakeOneFromInventorySlot] = new KeyOrMouse(Keys.LeftControl);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Enum.TryParse(attribute.Name.ToString(), true, out InputType inputType)) { continue; }
|
if (!Enum.TryParse(attribute.Name.ToString(), true, out InputType inputType)) { continue; }
|
||||||
|
|
||||||
if (int.TryParse(attribute.Value.ToString(), out int mouseButtonInt))
|
if (int.TryParse(attribute.Value.ToString(), out int mouseButtonInt))
|
||||||
@@ -199,6 +198,13 @@ namespace Barotrauma
|
|||||||
keyMapping[(int)inputType] = new KeyOrMouse(key);
|
keyMapping[(int)inputType] = new KeyOrMouse(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//v0.15 added creature attacks that can be used with a character capable of speaking (with mudraptor or spineling genes),
|
||||||
|
//which causes the previous attack keybind R to conflict with the radio keybind
|
||||||
|
// -> automatically change it to F
|
||||||
|
if (gameVersion < new Version(0, 15, 0, 0))
|
||||||
|
{
|
||||||
|
keyMapping[(int)InputType.Attack] = new KeyOrMouse(Keys.F);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadInventoryKeybinds(XElement element)
|
private void LoadInventoryKeybinds(XElement element)
|
||||||
@@ -223,10 +229,12 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private void LoadControls(XDocument doc)
|
private void LoadControls(XDocument doc)
|
||||||
{
|
{
|
||||||
|
var gameVersion = new Version(doc.Root.GetAttributeString("gameversion", "0.0.0.0"));
|
||||||
|
|
||||||
XElement keyMapping = doc.Root.Element("keymapping");
|
XElement keyMapping = doc.Root.Element("keymapping");
|
||||||
if (keyMapping != null)
|
if (keyMapping != null)
|
||||||
{
|
{
|
||||||
LoadKeyBinds(keyMapping);
|
LoadKeyBinds(keyMapping, gameVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
XElement inventoryKeyMapping = doc.Root.Element("inventorykeymapping");
|
XElement inventoryKeyMapping = doc.Root.Element("inventorykeymapping");
|
||||||
@@ -1518,6 +1526,12 @@ namespace Barotrauma
|
|||||||
"Automatic quickstart enabled",
|
"Automatic quickstart enabled",
|
||||||
"Will the game automatically move on to Quickstart when the game is launched");
|
"Will the game automatically move on to Quickstart when the game is launched");
|
||||||
|
|
||||||
|
addDebugTickBox(
|
||||||
|
TestScreenEnabled,
|
||||||
|
(b) => TestScreenEnabled = b,
|
||||||
|
"Test screen enabled",
|
||||||
|
"Will the game automatically move on to a test screen when the game is launched");
|
||||||
|
|
||||||
addDebugTickBox(
|
addDebugTickBox(
|
||||||
AutomaticCampaignLoadEnabled,
|
AutomaticCampaignLoadEnabled,
|
||||||
(b) => AutomaticCampaignLoadEnabled = b,
|
(b) => AutomaticCampaignLoadEnabled = b,
|
||||||
@@ -1831,6 +1845,7 @@ namespace Barotrauma
|
|||||||
ic.ParseMsg();
|
ic.ParseMsg();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
CharacterHUD.ShouldRecreateHudTexts = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ApplySettings()
|
private void ApplySettings()
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public override void CreateSlots()
|
public override void CreateSlots()
|
||||||
{
|
{
|
||||||
if (visualSlots == null) { visualSlots = new VisualSlot[capacity]; }
|
visualSlots ??= new VisualSlot[capacity];
|
||||||
|
|
||||||
float multiplier = !GUI.IsFourByThree() ? UIScale : UIScale * 0.925f;
|
float multiplier = !GUI.IsFourByThree() ? UIScale : UIScale * 0.925f;
|
||||||
|
|
||||||
@@ -175,6 +175,12 @@ namespace Barotrauma
|
|||||||
(int)SlotPositions[i].Y,
|
(int)SlotPositions[i].Y,
|
||||||
(int)(slotSprite.size.X * multiplier), (int)(slotSprite.size.Y * multiplier));
|
(int)(slotSprite.size.X * multiplier), (int)(slotSprite.size.Y * multiplier));
|
||||||
|
|
||||||
|
if (SlotTypes[i] == InvSlotType.HealthInterface &&
|
||||||
|
character.CharacterHealth?.InventorySlotContainer != null)
|
||||||
|
{
|
||||||
|
slotRect.Width = slotRect.Height = (int)(character.CharacterHealth.InventorySlotContainer.Rect.Width * 1.2f);
|
||||||
|
}
|
||||||
|
|
||||||
ItemContainer itemContainer = slots[i].FirstOrDefault()?.GetComponent<ItemContainer>();
|
ItemContainer itemContainer = slots[i].FirstOrDefault()?.GetComponent<ItemContainer>();
|
||||||
if (itemContainer != null)
|
if (itemContainer != null)
|
||||||
{
|
{
|
||||||
@@ -238,6 +244,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (visualSlots[i].Disabled || (slots[i].HideIfEmpty && slots[i].Empty())) { return true; }
|
if (visualSlots[i].Disabled || (slots[i].HideIfEmpty && slots[i].Empty())) { return true; }
|
||||||
|
|
||||||
|
if (CharacterHealth.OpenHealthWindow != Character.Controlled?.CharacterHealth && SlotTypes[i] == InvSlotType.HealthInterface) { return true; }
|
||||||
|
|
||||||
if (layout == Layout.Default)
|
if (layout == Layout.Default)
|
||||||
{
|
{
|
||||||
if (PersonalSlots.HasFlag(SlotTypes[i]) && !personalSlotArea.Contains(visualSlots[i].Rect.Center + visualSlots[i].DrawOffset.ToPoint())) { return true; }
|
if (PersonalSlots.HasFlag(SlotTypes[i]) && !personalSlotArea.Contains(visualSlots[i].Rect.Center + visualSlots[i].DrawOffset.ToPoint())) { return true; }
|
||||||
@@ -315,7 +323,7 @@ namespace Barotrauma
|
|||||||
case Layout.Default:
|
case Layout.Default:
|
||||||
{
|
{
|
||||||
int personalSlotCount = SlotTypes.Count(s => PersonalSlots.HasFlag(s));
|
int personalSlotCount = SlotTypes.Count(s => PersonalSlots.HasFlag(s));
|
||||||
int normalSlotCount = SlotTypes.Count(s => !PersonalSlots.HasFlag(s));
|
int normalSlotCount = SlotTypes.Count(s => !PersonalSlots.HasFlag(s) && s != InvSlotType.HealthInterface);
|
||||||
|
|
||||||
int x = GameMain.GraphicsWidth / 2 - normalSlotCount * (SlotSize.X + Spacing) / 2;
|
int x = GameMain.GraphicsWidth / 2 - normalSlotCount * (SlotSize.X + Spacing) / 2;
|
||||||
int upperX = HUDLayoutSettings.BottomRightInfoArea.X - SlotSize.X - Spacing * 4 - HideButtonWidth;
|
int upperX = HUDLayoutSettings.BottomRightInfoArea.X - SlotSize.X - Spacing * 4 - HideButtonWidth;
|
||||||
@@ -359,7 +367,8 @@ namespace Barotrauma
|
|||||||
int personalSlotX = HUDLayoutSettings.InventoryAreaLower.Right - SlotSize.X - Spacing;
|
int personalSlotX = HUDLayoutSettings.InventoryAreaLower.Right - SlotSize.X - Spacing;
|
||||||
for (int i = 0; i < visualSlots.Length; i++)
|
for (int i = 0; i < visualSlots.Length; i++)
|
||||||
{
|
{
|
||||||
if (HideSlot(i)) continue;
|
if (HideSlot(i) || SlotTypes[i] == InvSlotType.HealthInterface) { continue; }
|
||||||
|
if (SlotTypes[i] == InvSlotType.RightHand || SlotTypes[i] == InvSlotType.LeftHand) { continue; }
|
||||||
if (PersonalSlots.HasFlag(SlotTypes[i]))
|
if (PersonalSlots.HasFlag(SlotTypes[i]))
|
||||||
{
|
{
|
||||||
//upperX -= slotSize.X + spacing;
|
//upperX -= slotSize.X + spacing;
|
||||||
@@ -371,10 +380,18 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
int lowerX = x;
|
int lowerX = x;
|
||||||
|
int handSlotX = x;
|
||||||
int personalSlotY = GameMain.GraphicsHeight - bottomOffset * 2 - Spacing * 2 - (int)(!GUI.IsFourByThree() ? UnequippedIndicator.size.Y * UIScale * IndicatorScaleAdjustment : UnequippedIndicator.size.Y * UIScale * IndicatorScaleAdjustment * 2f);
|
int personalSlotY = GameMain.GraphicsHeight - bottomOffset * 2 - Spacing * 2 - (int)(!GUI.IsFourByThree() ? UnequippedIndicator.size.Y * UIScale * IndicatorScaleAdjustment : UnequippedIndicator.size.Y * UIScale * IndicatorScaleAdjustment * 2f);
|
||||||
for (int i = 0; i < SlotPositions.Length; i++)
|
for (int i = 0; i < SlotPositions.Length; i++)
|
||||||
{
|
{
|
||||||
if (HideSlot(i)) continue;
|
if (SlotTypes[i] == InvSlotType.RightHand || SlotTypes[i] == InvSlotType.LeftHand)
|
||||||
|
{
|
||||||
|
SlotPositions[i] = new Vector2(handSlotX, personalSlotY);
|
||||||
|
handSlotX += visualSlots[i].Rect.Width + Spacing;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HideSlot(i) || SlotTypes[i] == InvSlotType.HealthInterface) { continue; }
|
||||||
if (PersonalSlots.HasFlag(SlotTypes[i]))
|
if (PersonalSlots.HasFlag(SlotTypes[i]))
|
||||||
{
|
{
|
||||||
SlotPositions[i] = new Vector2(personalSlotX, personalSlotY);
|
SlotPositions[i] = new Vector2(personalSlotX, personalSlotY);
|
||||||
@@ -390,7 +407,8 @@ namespace Barotrauma
|
|||||||
x = lowerX;
|
x = lowerX;
|
||||||
for (int i = 0; i < SlotPositions.Length; i++)
|
for (int i = 0; i < SlotPositions.Length; i++)
|
||||||
{
|
{
|
||||||
if (!HideSlot(i)) continue;
|
if (!HideSlot(i) || SlotTypes[i] == InvSlotType.HealthInterface) { continue; }
|
||||||
|
if (SlotTypes[i] == InvSlotType.RightHand || SlotTypes[i] == InvSlotType.LeftHand) { continue; }
|
||||||
x -= visualSlots[i].Rect.Width + Spacing;
|
x -= visualSlots[i].Rect.Width + Spacing;
|
||||||
SlotPositions[i] = new Vector2(x, GameMain.GraphicsHeight - bottomOffset);
|
SlotPositions[i] = new Vector2(x, GameMain.GraphicsHeight - bottomOffset);
|
||||||
}
|
}
|
||||||
@@ -404,7 +422,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
for (int i = 0; i < SlotPositions.Length; i++)
|
for (int i = 0; i < SlotPositions.Length; i++)
|
||||||
{
|
{
|
||||||
if (HideSlot(i)) continue;
|
if (HideSlot(i) || SlotTypes[i] == InvSlotType.HealthInterface) { continue; }
|
||||||
|
if (SlotTypes[i] == InvSlotType.RightHand || SlotTypes[i] == InvSlotType.LeftHand) { continue; }
|
||||||
if (PersonalSlots.HasFlag(SlotTypes[i]))
|
if (PersonalSlots.HasFlag(SlotTypes[i]))
|
||||||
{
|
{
|
||||||
SlotPositions[i] = new Vector2(personalSlotX, personalSlotY);
|
SlotPositions[i] = new Vector2(personalSlotX, personalSlotY);
|
||||||
@@ -416,9 +435,16 @@ namespace Barotrauma
|
|||||||
x += visualSlots[i].Rect.Width + Spacing;
|
x += visualSlots[i].Rect.Width + Spacing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
int handSlotX = x - visualSlots[0].Rect.Width - Spacing;
|
||||||
for (int i = 0; i < SlotPositions.Length; i++)
|
for (int i = 0; i < SlotPositions.Length; i++)
|
||||||
{
|
{
|
||||||
if (!HideSlot(i)) continue;
|
if (SlotTypes[i] == InvSlotType.RightHand || SlotTypes[i] == InvSlotType.LeftHand)
|
||||||
|
{
|
||||||
|
bool rightSlot = SlotTypes[i] == InvSlotType.RightHand;
|
||||||
|
SlotPositions[i] = new Vector2(rightSlot ? handSlotX : handSlotX - visualSlots[0].Rect.Width - Spacing, personalSlotY);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!HideSlot(i) || SlotTypes[i] == InvSlotType.HealthInterface) { continue; }
|
||||||
SlotPositions[i] = new Vector2(x, GameMain.GraphicsHeight - bottomOffset);
|
SlotPositions[i] = new Vector2(x, GameMain.GraphicsHeight - bottomOffset);
|
||||||
x += visualSlots[i].Rect.Width + Spacing;
|
x += visualSlots[i].Rect.Width + Spacing;
|
||||||
}
|
}
|
||||||
@@ -432,7 +458,7 @@ namespace Barotrauma
|
|||||||
int x = startX, y = startY;
|
int x = startX, y = startY;
|
||||||
for (int i = 0; i < SlotPositions.Length; i++)
|
for (int i = 0; i < SlotPositions.Length; i++)
|
||||||
{
|
{
|
||||||
if (HideSlot(i)) continue;
|
if (HideSlot(i) || SlotTypes[i] == InvSlotType.HealthInterface) { continue; }
|
||||||
if (SlotTypes[i] == InvSlotType.Card || SlotTypes[i] == InvSlotType.Headset || SlotTypes[i] == InvSlotType.InnerClothes)
|
if (SlotTypes[i] == InvSlotType.Card || SlotTypes[i] == InvSlotType.Headset || SlotTypes[i] == InvSlotType.InnerClothes)
|
||||||
{
|
{
|
||||||
SlotPositions[i] = new Vector2(x, y);
|
SlotPositions[i] = new Vector2(x, y);
|
||||||
@@ -444,7 +470,7 @@ namespace Barotrauma
|
|||||||
int n = 0;
|
int n = 0;
|
||||||
for (int i = 0; i < SlotPositions.Length; i++)
|
for (int i = 0; i < SlotPositions.Length; i++)
|
||||||
{
|
{
|
||||||
if (HideSlot(i)) continue;
|
if (HideSlot(i) || SlotTypes[i] == InvSlotType.HealthInterface) { continue; }
|
||||||
if (SlotTypes[i] != InvSlotType.Card && SlotTypes[i] != InvSlotType.Headset && SlotTypes[i] != InvSlotType.InnerClothes)
|
if (SlotTypes[i] != InvSlotType.Card && SlotTypes[i] != InvSlotType.Headset && SlotTypes[i] != InvSlotType.InnerClothes)
|
||||||
{
|
{
|
||||||
SlotPositions[i] = new Vector2(x, y);
|
SlotPositions[i] = new Vector2(x, y);
|
||||||
@@ -462,12 +488,22 @@ namespace Barotrauma
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (character.CharacterHealth?.UseHealthWindow ?? false)
|
||||||
|
{
|
||||||
|
Vector2 pos = character.CharacterHealth.InventorySlotContainer.Rect.Location.ToVector2();
|
||||||
|
for (int i = 0; i < capacity; i++)
|
||||||
|
{
|
||||||
|
if (SlotTypes[i] != InvSlotType.HealthInterface) { continue; }
|
||||||
|
SlotPositions[i] = pos;
|
||||||
|
pos.Y += visualSlots[i].Rect.Height + Spacing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CreateSlots();
|
CreateSlots();
|
||||||
if (layout == Layout.Default)
|
if (layout == Layout.Default)
|
||||||
{
|
{
|
||||||
HUDLayoutSettings.InventoryTopY = visualSlots[0].EquipButtonRect.Y - (int)(15 * GUI.Scale);
|
HUDLayoutSettings.InventoryTopY = visualSlots[0].EquipButtonRect.Y - (int)(15 * GUI.Scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ControlInput(Camera cam)
|
protected override void ControlInput(Camera cam)
|
||||||
@@ -652,6 +688,11 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
//if putting an item to a container with a max stack size of 1, only put one item from the stack
|
||||||
|
if (quickUseAction == QuickUseAction.PutToContainer && (character.SelectedConstruction?.GetComponent<ItemContainer>()?.MaxStackSize ?? 0) <= 1)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -661,7 +702,7 @@ namespace Barotrauma
|
|||||||
if (item != null)
|
if (item != null)
|
||||||
{
|
{
|
||||||
var slot = visualSlots[i];
|
var slot = visualSlots[i];
|
||||||
if (item.AllowedSlots.Any(a => a != InvSlotType.Any))
|
if (item.AllowedSlots.Any(a => a != InvSlotType.Any && a != InvSlotType.HealthInterface))
|
||||||
{
|
{
|
||||||
HandleButtonEquipStates(item, slot, deltaTime);
|
HandleButtonEquipStates(item, slot, deltaTime);
|
||||||
}
|
}
|
||||||
@@ -840,7 +881,9 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private QuickUseAction GetQuickUseAction(Item item, bool allowEquip, bool allowInventorySwap, bool allowApplyTreatment)
|
private QuickUseAction GetQuickUseAction(Item item, bool allowEquip, bool allowInventorySwap, bool allowApplyTreatment)
|
||||||
{
|
{
|
||||||
if (allowApplyTreatment && CharacterHealth.OpenHealthWindow != null)
|
if (allowApplyTreatment && CharacterHealth.OpenHealthWindow != null &&
|
||||||
|
//if the item can be equipped in the health interface slot, don't use it as a treatment but try to equip it
|
||||||
|
!item.AllowedSlots.Contains(InvSlotType.HealthInterface))
|
||||||
{
|
{
|
||||||
return QuickUseAction.UseTreatment;
|
return QuickUseAction.UseTreatment;
|
||||||
}
|
}
|
||||||
@@ -1135,7 +1178,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
for (int i = 0; i < capacity; i++)
|
for (int i = 0; i < capacity; i++)
|
||||||
{
|
{
|
||||||
if (HideSlot(i)) { continue; }
|
if (HideSlot(i) || SlotTypes[i] == InvSlotType.HealthInterface) { continue; }
|
||||||
|
|
||||||
//don't draw the item if it's being dragged out of the slot
|
//don't draw the item if it's being dragged out of the slot
|
||||||
bool drawItem = !DraggingItems.Any() || !slots[i].Items.All(it => DraggingItems.Contains(it)) || visualSlots[i].MouseOn();
|
bool drawItem = !DraggingItems.Any() || !slots[i].Items.All(it => DraggingItems.Contains(it)) || visualSlots[i].MouseOn();
|
||||||
@@ -1189,7 +1232,7 @@ namespace Barotrauma
|
|||||||
highlightedQuickUseSlot = visualSlots[i];
|
highlightedQuickUseSlot = visualSlots[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!slots[i].First().AllowedSlots.Any(a => a == InvSlotType.Any))
|
if (slots[i].First().AllowedSlots.Count() == 1 || SlotTypes[i] == InvSlotType.HealthInterface)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
|
namespace Barotrauma.Items.Components
|
||||||
|
{
|
||||||
|
internal partial class EntitySpawnerComponent
|
||||||
|
{
|
||||||
|
public Vector2 DrawSize => Vector2.Zero;
|
||||||
|
|
||||||
|
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
|
||||||
|
{
|
||||||
|
if (!editing) { return; }
|
||||||
|
|
||||||
|
switch (SpawnAreaShape)
|
||||||
|
{
|
||||||
|
case AreaShape.Rectangle:
|
||||||
|
{
|
||||||
|
RectangleF rect = GetAreaRectangle(SpawnAreaBounds, SpawnAreaOffset, draw: true);
|
||||||
|
GUI.DrawRectangle(spriteBatch, rect.Location, rect.Size, GUI.Style.Red, isFilled: false, 0f, 4f);
|
||||||
|
|
||||||
|
if (MaximumAmountRangePadding > 0f)
|
||||||
|
{
|
||||||
|
rect.Inflate(MaximumAmountRangePadding, MaximumAmountRangePadding);
|
||||||
|
GUI.DrawRectangle(spriteBatch, rect.Location, rect.Size, GUI.Style.Red, isFilled: false, 0f, 2f);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AreaShape.Circle:
|
||||||
|
Vector2 center = item.WorldPosition;
|
||||||
|
center.Y = -center.Y;
|
||||||
|
center += SpawnAreaOffset;
|
||||||
|
spriteBatch.DrawCircle(center, SpawnAreaRadius, 32, GUI.Style.Red, thickness: 4f);
|
||||||
|
|
||||||
|
if (MaximumAmountRangePadding > 0f)
|
||||||
|
{
|
||||||
|
spriteBatch.DrawCircle(center, SpawnAreaRadius + MaximumAmountRangePadding, 32, GUI.Style.Red, thickness: 2f);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!OnlySpawnWhenCrewInRange) { return; }
|
||||||
|
|
||||||
|
switch (CrewAreaShape)
|
||||||
|
{
|
||||||
|
case AreaShape.Rectangle:
|
||||||
|
{
|
||||||
|
RectangleF rect = GetAreaRectangle(CrewAreaBounds, CrewAreaOffset, draw: true);
|
||||||
|
GUI.DrawRectangle(spriteBatch, rect.Location, rect.Size, GUI.Style.Green, isFilled: false, 0f, 4f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AreaShape.Circle:
|
||||||
|
Vector2 center = item.WorldPosition;
|
||||||
|
center.Y = -center.Y;
|
||||||
|
center += CrewAreaOffset;
|
||||||
|
spriteBatch.DrawCircle(center, CrewAreaRadius, 32, GUI.Style.Green);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
using Barotrauma.Networking;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Barotrauma.Items.Components
|
||||||
|
{
|
||||||
|
partial class GeneticMaterial : ItemComponent
|
||||||
|
{
|
||||||
|
[Serialize(0.0f, false)]
|
||||||
|
public float TooltipValueMin { get; set; }
|
||||||
|
|
||||||
|
[Serialize(0.0f, false)]
|
||||||
|
public float TooltipValueMax { get; set; }
|
||||||
|
|
||||||
|
public override void AddTooltipInfo(ref string name, ref string description)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(materialName) && item.ContainedItems.Count() > 0)
|
||||||
|
{
|
||||||
|
string mergedMaterialName = materialName;
|
||||||
|
foreach (Item containedItem in item.ContainedItems)
|
||||||
|
{
|
||||||
|
var containedMaterial = containedItem.GetComponent<GeneticMaterial>();
|
||||||
|
if (containedMaterial == null) { continue; }
|
||||||
|
mergedMaterialName += ", " + containedMaterial.materialName;
|
||||||
|
}
|
||||||
|
name = name.Replace(materialName, mergedMaterialName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Tainted)
|
||||||
|
{
|
||||||
|
name = TextManager.GetWithVariable("entityname.taintedgeneticmaterial", "[geneticmaterialname]", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TextManager.ContainsTag("entitydescription." + Item.prefab.Identifier))
|
||||||
|
{
|
||||||
|
int value = (int)MathHelper.Lerp(TooltipValueMin, TooltipValueMax, item.ConditionPercentage / 100.0f);
|
||||||
|
description = TextManager.GetWithVariable("entitydescription." + Item.prefab.Identifier, "[value]", value.ToString());
|
||||||
|
}
|
||||||
|
foreach (Item containedItem in item.ContainedItems)
|
||||||
|
{
|
||||||
|
var containedGeneticMaterial = containedItem.GetComponent<GeneticMaterial>();
|
||||||
|
if (containedGeneticMaterial == null) { continue; }
|
||||||
|
string _ = string.Empty;
|
||||||
|
string containedDescription = containedItem.Description;
|
||||||
|
containedGeneticMaterial.AddTooltipInfo(ref _, ref containedDescription);
|
||||||
|
if (!string.IsNullOrEmpty(containedDescription))
|
||||||
|
{
|
||||||
|
description += '\n' + containedDescription;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ModifyDeconstructInfo(Deconstructor deconstructor, ref string buttonText, ref string infoText)
|
||||||
|
{
|
||||||
|
if (deconstructor.InputContainer.Inventory.AllItems.Count() == 2)
|
||||||
|
{
|
||||||
|
if (!deconstructor.InputContainer.Inventory.AllItems.All(it => it.prefab == item.prefab))
|
||||||
|
{
|
||||||
|
buttonText = TextManager.Get("researchstation.combine");
|
||||||
|
infoText = TextManager.Get("researchstation.combine.infotext");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buttonText = TextManager.Get("researchstation.refine");
|
||||||
|
int taintedProbability = (int)(GetTaintedProbabilityOnRefine(Character.Controlled) * 100);
|
||||||
|
infoText = TextManager.GetWithVariable("researchstation.refine.infotext", "[taintedprobability]", taintedProbability.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||||
|
{
|
||||||
|
Tainted = msg.ReadBoolean();
|
||||||
|
if (Tainted)
|
||||||
|
{
|
||||||
|
uint selectedTaintedEffectId = msg.ReadUInt32();
|
||||||
|
selectedTaintedEffect = AfflictionPrefab.Prefabs.Find(a => a.UIntIdentifier == selectedTaintedEffectId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint selectedEffectId = msg.ReadUInt32();
|
||||||
|
selectedEffect = AfflictionPrefab.Prefabs.Find(a => a.UIntIdentifier == selectedEffectId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,201 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using System;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
using Barotrauma.Extensions;
|
||||||
|
using Barotrauma.IO;
|
||||||
|
|
||||||
namespace Barotrauma.Items.Components
|
namespace Barotrauma.Items.Components
|
||||||
{
|
{
|
||||||
partial class IdCard
|
partial class IdCard
|
||||||
{
|
{
|
||||||
public Sprite StoredPortrait;
|
public struct OwnerAppearance
|
||||||
public Vector2 StoredSheetIndex;
|
{
|
||||||
public JobPrefab StoredJobPrefab;
|
public Sprite Portrait;
|
||||||
public List<WearableSprite> StoredAttachments;
|
public Vector2 SheetIndex;
|
||||||
|
public JobPrefab JobPrefab;
|
||||||
|
public List<WearableSprite> Attachments;
|
||||||
|
public Color HairColor;
|
||||||
|
public Color FacialHairColor;
|
||||||
|
public Color SkinColor;
|
||||||
|
|
||||||
|
public void ExtractJobPrefab(string[] tags)
|
||||||
|
{
|
||||||
|
string jobIdTag = tags.FirstOrDefault(s => s.StartsWith("jobid:"));
|
||||||
|
|
||||||
|
if (jobIdTag != null && jobIdTag.Length > 6)
|
||||||
|
{
|
||||||
|
string jobId = jobIdTag.Substring(6);
|
||||||
|
if (jobId != string.Empty)
|
||||||
|
{
|
||||||
|
JobPrefab = JobPrefab.Get(jobId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ExtractAppearance(CharacterInfo characterInfo, string[] tags)
|
||||||
|
{
|
||||||
|
Gender disguisedGender = Gender.None;
|
||||||
|
Race disguisedRace = Race.None;
|
||||||
|
int disguisedHeadSpriteId = -1;
|
||||||
|
int disguisedHairIndex = -1;
|
||||||
|
int disguisedBeardIndex = -1;
|
||||||
|
int disguisedMoustacheIndex = -1;
|
||||||
|
int disguisedFaceAttachmentIndex = -1;
|
||||||
|
Color hairColor = Color.Black;
|
||||||
|
Color facialHairColor = Color.Black;
|
||||||
|
Color skinColor = Color.Black;
|
||||||
|
|
||||||
|
foreach (string tag in tags)
|
||||||
|
{
|
||||||
|
string[] s = tag.Split(':');
|
||||||
|
|
||||||
|
switch (s[0].ToLowerInvariant())
|
||||||
|
{
|
||||||
|
case "haircolor":
|
||||||
|
hairColor = XMLExtensions.ParseColor(s[1]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "facialhaircolor":
|
||||||
|
facialHairColor = XMLExtensions.ParseColor(s[1]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "skincolor":
|
||||||
|
skinColor = XMLExtensions.ParseColor(s[1]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "gender":
|
||||||
|
Enum.TryParse(s[1], ignoreCase: true, out disguisedGender);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "race":
|
||||||
|
Enum.TryParse(s[1], ignoreCase: true, out disguisedRace);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "headspriteid":
|
||||||
|
int.TryParse(s[1], NumberStyles.Any, CultureInfo.InvariantCulture, out disguisedHeadSpriteId);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "hairindex":
|
||||||
|
disguisedHairIndex = int.Parse(s[1]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "beardindex":
|
||||||
|
disguisedBeardIndex = int.Parse(s[1]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "moustacheindex":
|
||||||
|
disguisedMoustacheIndex = int.Parse(s[1]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "faceattachmentindex":
|
||||||
|
disguisedFaceAttachmentIndex = int.Parse(s[1]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "sheetindex":
|
||||||
|
string[] vectorValues = s[1].Split(";");
|
||||||
|
SheetIndex = new Vector2(float.Parse(vectorValues[0]), float.Parse(vectorValues[1]));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((characterInfo.HasGenders && disguisedGender == Gender.None)
|
||||||
|
|| (characterInfo.HasRaces && disguisedRace == Race.None)
|
||||||
|
|| disguisedHeadSpriteId <= 0)
|
||||||
|
{
|
||||||
|
Portrait = null;
|
||||||
|
Attachments = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (XElement limbElement in characterInfo.Ragdoll.MainElement.Elements())
|
||||||
|
{
|
||||||
|
if (!limbElement.GetAttributeString("type", "").Equals("head", StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||||
|
|
||||||
|
XElement spriteElement = limbElement.Element("sprite");
|
||||||
|
if (spriteElement == null) { continue; }
|
||||||
|
|
||||||
|
string spritePath = spriteElement.Attribute("texture").Value;
|
||||||
|
|
||||||
|
spritePath = spritePath.Replace("[GENDER]", disguisedGender.ToString().ToLowerInvariant());
|
||||||
|
spritePath = spritePath.Replace("[RACE]", disguisedRace.ToString().ToLowerInvariant());
|
||||||
|
spritePath = spritePath.Replace("[HEADID]", disguisedHeadSpriteId.ToString());
|
||||||
|
|
||||||
|
string fileName = Path.GetFileNameWithoutExtension(spritePath);
|
||||||
|
|
||||||
|
//go through the files in the directory to find a matching sprite
|
||||||
|
foreach (string file in Directory.GetFiles(Path.GetDirectoryName(spritePath)))
|
||||||
|
{
|
||||||
|
if (!file.EndsWith(".png", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
string fileWithoutTags = Path.GetFileNameWithoutExtension(file);
|
||||||
|
fileWithoutTags = fileWithoutTags.Split('[', ']').First();
|
||||||
|
if (fileWithoutTags != fileName) { continue; }
|
||||||
|
Portrait = new Sprite(spriteElement, "", file) { RelativeOrigin = Vector2.Zero };
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (characterInfo.Wearables != null)
|
||||||
|
{
|
||||||
|
float baldnessChance = disguisedGender == Gender.Female ? 0.05f : 0.2f;
|
||||||
|
|
||||||
|
List<XElement> createElementList(WearableType wearableType, float emptyCommonness = 1.0f)
|
||||||
|
=> CharacterInfo.AddEmpty(
|
||||||
|
characterInfo.FilterByTypeAndHeadID(
|
||||||
|
characterInfo.FilterElementsByGenderAndRace(characterInfo.Wearables, disguisedGender, disguisedRace),
|
||||||
|
wearableType, disguisedHeadSpriteId),
|
||||||
|
wearableType, emptyCommonness);
|
||||||
|
|
||||||
|
var disguisedHairs = createElementList(WearableType.Hair, baldnessChance);
|
||||||
|
var disguisedBeards = createElementList(WearableType.Beard);
|
||||||
|
var disguisedMoustaches = createElementList(WearableType.Moustache);
|
||||||
|
var disguisedFaceAttachments = createElementList(WearableType.FaceAttachment);
|
||||||
|
|
||||||
|
XElement getElementFromList(List<XElement> list, int index)
|
||||||
|
=> CharacterInfo.IsValidIndex(index, list)
|
||||||
|
? list[index]
|
||||||
|
: characterInfo.GetRandomElement(list);
|
||||||
|
|
||||||
|
var disguisedHairElement = getElementFromList(disguisedHairs, disguisedHairIndex);
|
||||||
|
var disguisedBeardElement = getElementFromList(disguisedBeards, disguisedBeardIndex);
|
||||||
|
var disguisedMoustacheElement = getElementFromList(disguisedMoustaches, disguisedMoustacheIndex);
|
||||||
|
var disguisedFaceAttachmentElement = getElementFromList(disguisedFaceAttachments, disguisedFaceAttachmentIndex);
|
||||||
|
|
||||||
|
Attachments = new List<WearableSprite>();
|
||||||
|
|
||||||
|
void loadAttachments(List<WearableSprite> attachments, XElement element, WearableType wearableType)
|
||||||
|
{
|
||||||
|
foreach (var s in element?.Elements("sprite") ?? Enumerable.Empty<XElement>())
|
||||||
|
{
|
||||||
|
attachments.Add(new WearableSprite(s, wearableType));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadAttachments(Attachments, disguisedFaceAttachmentElement, WearableType.FaceAttachment);
|
||||||
|
loadAttachments(Attachments, disguisedBeardElement, WearableType.Beard);
|
||||||
|
loadAttachments(Attachments, disguisedMoustacheElement, WearableType.Moustache);
|
||||||
|
loadAttachments(Attachments, disguisedHairElement, WearableType.Hair);
|
||||||
|
|
||||||
|
loadAttachments(Attachments,
|
||||||
|
characterInfo.OmitJobInPortraitClothing
|
||||||
|
? JobPrefab.NoJobElement?.Element("PortraitClothing")
|
||||||
|
: JobPrefab?.ClothingElement,
|
||||||
|
WearableType.JobIndicator);
|
||||||
|
}
|
||||||
|
|
||||||
|
HairColor = hairColor;
|
||||||
|
FacialHairColor = facialHairColor;
|
||||||
|
SkinColor = skinColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public OwnerAppearance StoredOwnerAppearance = default;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ using System.Collections.Generic;
|
|||||||
using Barotrauma.IO;
|
using Barotrauma.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
using Barotrauma.Sounds;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Barotrauma.Items.Components
|
namespace Barotrauma.Items.Components
|
||||||
{
|
{
|
||||||
@@ -18,7 +20,11 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
protected float currentCrossHairScale, currentCrossHairPointerScale;
|
protected float currentCrossHairScale, currentCrossHairPointerScale;
|
||||||
|
|
||||||
|
private RoundSound chargeSound;
|
||||||
|
private SoundChannel chargeSoundChannel;
|
||||||
|
|
||||||
private readonly List<ParticleEmitter> particleEmitters = new List<ParticleEmitter>();
|
private readonly List<ParticleEmitter> particleEmitters = new List<ParticleEmitter>();
|
||||||
|
private readonly List<ParticleEmitter> particleEmitterCharges = new List<ParticleEmitter>();
|
||||||
|
|
||||||
[Serialize(1.0f, false, description: "The scale of the crosshair sprite (if there is one).")]
|
[Serialize(1.0f, false, description: "The scale of the crosshair sprite (if there is one).")]
|
||||||
public float CrossHairScale
|
public float CrossHairScale
|
||||||
@@ -48,6 +54,12 @@ namespace Barotrauma.Items.Components
|
|||||||
case "particleemitter":
|
case "particleemitter":
|
||||||
particleEmitters.Add(new ParticleEmitter(subElement));
|
particleEmitters.Add(new ParticleEmitter(subElement));
|
||||||
break;
|
break;
|
||||||
|
case "particleemittercharge":
|
||||||
|
particleEmitterCharges.Add(new ParticleEmitter(subElement));
|
||||||
|
break;
|
||||||
|
case "chargesound":
|
||||||
|
chargeSound = Submarine.LoadRoundSound(subElement, false);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,15 +96,62 @@ namespace Barotrauma.Items.Components
|
|||||||
crosshairPointerPos = PlayerInput.MousePosition;
|
crosshairPointerPos = PlayerInput.MousePosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
partial void UpdateProjSpecific(float deltaTime)
|
||||||
|
{
|
||||||
|
float chargeRatio = currentChargeTime / MaxChargeTime;
|
||||||
|
|
||||||
|
switch (currentChargingState)
|
||||||
|
{
|
||||||
|
case ChargingState.WindingUp:
|
||||||
|
case ChargingState.WindingDown:
|
||||||
|
Vector2 particlePos = item.WorldPosition + ConvertUnits.ToDisplayUnits(TransformedBarrelPos);
|
||||||
|
float sizeMultiplier = Math.Clamp(chargeRatio, 0.1f, 1f);
|
||||||
|
foreach (ParticleEmitter emitter in particleEmitterCharges)
|
||||||
|
{
|
||||||
|
emitter.Emit(deltaTime, particlePos, hullGuess: null, sizeMultiplier: sizeMultiplier, colorMultiplier: emitter.Prefab.Properties.ColorMultiplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chargeSoundChannel == null || !chargeSoundChannel.IsPlaying)
|
||||||
|
{
|
||||||
|
if (chargeSound != null)
|
||||||
|
{
|
||||||
|
chargeSoundChannel = SoundPlayer.PlaySound(chargeSound.Sound, item.WorldPosition, chargeSound.Volume, chargeSound.Range, ignoreMuffling: chargeSound.IgnoreMuffling);
|
||||||
|
if (chargeSoundChannel != null) chargeSoundChannel.Looping = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (chargeSoundChannel != null)
|
||||||
|
{
|
||||||
|
chargeSoundChannel.FrequencyMultiplier = MathHelper.Lerp(0.5f, 1.5f, chargeRatio);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (chargeSoundChannel != null)
|
||||||
|
{
|
||||||
|
if (chargeSoundChannel.IsPlaying)
|
||||||
|
{
|
||||||
|
chargeSoundChannel.FadeOutAndDispose();
|
||||||
|
chargeSoundChannel.Looping = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
chargeSoundChannel = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||||
{
|
{
|
||||||
if (character == null || !character.IsKeyDown(InputType.Aim)) { return; }
|
if (character == null || !character.IsKeyDown(InputType.Aim)) { return; }
|
||||||
|
|
||||||
//camera focused on some other item/device, don't draw the crosshair
|
//camera focused on some other item/device, don't draw the crosshair
|
||||||
if (character.ViewTarget != null && (character.ViewTarget is Item item) && item.Prefab.FocusOnSelected) { return; }
|
if (character.ViewTarget != null && (character.ViewTarget is Item viewTargetItem) && viewTargetItem.Prefab.FocusOnSelected) { return; }
|
||||||
|
//don't draw the crosshair if the item is in some other type of equip slot than hands (e.g. assault rifle in the bag slot)
|
||||||
|
if (!character.HeldItems.Contains(item)) { return; }
|
||||||
|
|
||||||
GUI.HideCursor = (crosshairSprite != null || crosshairPointerSprite != null) &&
|
GUI.HideCursor = (crosshairSprite != null || crosshairPointerSprite != null) &&
|
||||||
GUI.MouseOn == null && !Inventory.IsMouseOnInventory() && !GameMain.Instance.Paused;
|
GUI.MouseOn == null && !Inventory.IsMouseOnInventory && !GameMain.Instance.Paused;
|
||||||
if (GUI.HideCursor)
|
if (GUI.HideCursor)
|
||||||
{
|
{
|
||||||
crosshairSprite?.Draw(spriteBatch, crosshairPos, Color.White, 0, currentCrossHairScale);
|
crosshairSprite?.Draw(spriteBatch, crosshairPos, Color.White, 0, currentCrossHairScale);
|
||||||
|
|||||||
@@ -246,6 +246,7 @@ namespace Barotrauma.Items.Components
|
|||||||
public void PlaySound(ActionType type, Character user = null)
|
public void PlaySound(ActionType type, Character user = null)
|
||||||
{
|
{
|
||||||
if (!hasSoundsOfType[(int)type]) { return; }
|
if (!hasSoundsOfType[(int)type]) { return; }
|
||||||
|
if (GameMain.Client?.MidRoundSyncing ?? false) { return; }
|
||||||
|
|
||||||
if (loopingSound != null)
|
if (loopingSound != null)
|
||||||
{
|
{
|
||||||
@@ -429,7 +430,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
foreach (ItemComponent component in item.Components)
|
foreach (ItemComponent component in item.Components)
|
||||||
{
|
{
|
||||||
if (component.name.ToLower() == LinkUIToComponent.ToLower())
|
if (component.name.Equals(LinkUIToComponent, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
linkToUIComponent = component;
|
linkToUIComponent = component;
|
||||||
}
|
}
|
||||||
@@ -443,9 +444,9 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
public virtual void DrawHUD(SpriteBatch spriteBatch, Character character) { }
|
public virtual void DrawHUD(SpriteBatch spriteBatch, Character character) { }
|
||||||
|
|
||||||
public virtual void AddToGUIUpdateList()
|
public virtual void AddToGUIUpdateList(int order = 0)
|
||||||
{
|
{
|
||||||
GuiFrame?.AddToGUIUpdateList();
|
GuiFrame?.AddToGUIUpdateList(order: order);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void UpdateHUD(Character character, float deltaTime, Camera cam) { }
|
public virtual void UpdateHUD(Character character, float deltaTime, Camera cam) { }
|
||||||
@@ -620,6 +621,6 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
OnResolutionChanged();
|
OnResolutionChanged();
|
||||||
}
|
}
|
||||||
public virtual void AddTooltipInfo(ref string description) { }
|
public virtual void AddTooltipInfo(ref string name, ref string description) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ namespace Barotrauma.Items.Components
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private float[] containedSpriteDepths;
|
private float[] containedSpriteDepths;
|
||||||
|
|
||||||
|
private Sprite[] slotIcons;
|
||||||
|
|
||||||
public Sprite InventoryTopSprite
|
public Sprite InventoryTopSprite
|
||||||
{
|
{
|
||||||
get { return inventoryTopSprite; }
|
get { return inventoryTopSprite; }
|
||||||
@@ -58,6 +60,9 @@ namespace Barotrauma.Items.Components
|
|||||||
[Serialize(null, false)]
|
[Serialize(null, false)]
|
||||||
public string ContainedStateIndicatorStyle { get; set; }
|
public string ContainedStateIndicatorStyle { get; set; }
|
||||||
|
|
||||||
|
[Serialize(-1, false, description: "Can be used to make the contained state indicator display the condition of the item in a specific slot even when the container's capacity is more than 1.")]
|
||||||
|
public int ContainedStateIndicatorSlot { get; set; }
|
||||||
|
|
||||||
[Serialize(true, false, description: "Should an indicator displaying the state of the contained items be displayed on this item's inventory slot. "+
|
[Serialize(true, false, description: "Should an indicator displaying the state of the contained items be displayed on this item's inventory slot. "+
|
||||||
"If this item can only contain one item, the indicator will display the condition of the contained item, otherwise it will indicate how full the item is.")]
|
"If this item can only contain one item, the indicator will display the condition of the contained item, otherwise it will indicate how full the item is.")]
|
||||||
public bool ShowContainedStateIndicator { get; set; }
|
public bool ShowContainedStateIndicator { get; set; }
|
||||||
@@ -85,6 +90,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
partial void InitProjSpecific(XElement element)
|
partial void InitProjSpecific(XElement element)
|
||||||
{
|
{
|
||||||
|
slotIcons = new Sprite[capacity];
|
||||||
foreach (XElement subElement in element.Elements())
|
foreach (XElement subElement in element.Elements())
|
||||||
{
|
{
|
||||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||||
@@ -104,6 +110,17 @@ namespace Barotrauma.Items.Components
|
|||||||
case "containedstateindicatorempty":
|
case "containedstateindicatorempty":
|
||||||
ContainedStateIndicatorEmpty = new Sprite(subElement);
|
ContainedStateIndicatorEmpty = new Sprite(subElement);
|
||||||
break;
|
break;
|
||||||
|
case "sloticon":
|
||||||
|
int index = subElement.GetAttributeInt("slotindex", -1);
|
||||||
|
Sprite icon = new Sprite(subElement);
|
||||||
|
for (int i = 0; i < capacity; i++)
|
||||||
|
{
|
||||||
|
if (i == index || index == -1)
|
||||||
|
{
|
||||||
|
slotIcons[i] = icon;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,7 +214,7 @@ namespace Barotrauma.Items.Components
|
|||||||
if (UILabel == string.Empty) { return string.Empty; }
|
if (UILabel == string.Empty) { return string.Empty; }
|
||||||
if (UILabel != null)
|
if (UILabel != null)
|
||||||
{
|
{
|
||||||
return TextManager.Get("UILabel." + UILabel);
|
return TextManager.Get("UILabel." + UILabel, returnNull: true) ?? TextManager.Get(UILabel);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -205,6 +222,12 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Sprite GetSlotIcon(int slotIndex)
|
||||||
|
{
|
||||||
|
if (slotIndex < 0 || slotIndex >= slotIcons.Length) { return null; }
|
||||||
|
return slotIcons[slotIndex];
|
||||||
|
}
|
||||||
|
|
||||||
public bool KeepOpenWhenEquippedBy(Character character)
|
public bool KeepOpenWhenEquippedBy(Character character)
|
||||||
{
|
{
|
||||||
if (!character.CanAccessInventory(Inventory) ||
|
if (!character.CanAccessInventory(Inventory) ||
|
||||||
@@ -266,7 +289,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Matrix transform = Matrix.CreateRotationZ(item.body.Rotation);
|
Matrix transform = Matrix.CreateRotationZ(item.body.DrawRotation);
|
||||||
if (item.body.Dir == -1.0f)
|
if (item.body.Dir == -1.0f)
|
||||||
{
|
{
|
||||||
transformedItemPos.X = -transformedItemPos.X;
|
transformedItemPos.X = -transformedItemPos.X;
|
||||||
@@ -277,7 +300,7 @@ namespace Barotrauma.Items.Components
|
|||||||
transformedItemPos = Vector2.Transform(transformedItemPos, transform);
|
transformedItemPos = Vector2.Transform(transformedItemPos, transform);
|
||||||
transformedItemInterval = Vector2.Transform(transformedItemInterval, transform);
|
transformedItemInterval = Vector2.Transform(transformedItemInterval, transform);
|
||||||
transformedItemIntervalHorizontal = Vector2.Transform(transformedItemIntervalHorizontal, transform);
|
transformedItemIntervalHorizontal = Vector2.Transform(transformedItemIntervalHorizontal, transform);
|
||||||
transformedItemPos += item.DrawPosition;
|
transformedItemPos += item.body.DrawPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2 currentItemPos = transformedItemPos;
|
Vector2 currentItemPos = transformedItemPos;
|
||||||
@@ -319,7 +342,7 @@ namespace Barotrauma.Items.Components
|
|||||||
new Vector2(currentItemPos.X, -currentItemPos.Y),
|
new Vector2(currentItemPos.X, -currentItemPos.Y),
|
||||||
isWiringMode ? containedItem.GetSpriteColor() * 0.15f : containedItem.GetSpriteColor(),
|
isWiringMode ? containedItem.GetSpriteColor() * 0.15f : containedItem.GetSpriteColor(),
|
||||||
origin,
|
origin,
|
||||||
-(containedItem.body == null ? 0.0f : containedItem.body.DrawRotation + MathHelper.ToRadians(-item.Rotation)),
|
-(containedItem.body == null ? 0.0f : containedItem.body.DrawRotation ),
|
||||||
containedItem.Scale,
|
containedItem.Scale,
|
||||||
spriteEffects,
|
spriteEffects,
|
||||||
depth: containedSpriteDepth);
|
depth: containedSpriteDepth);
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1)
|
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1)
|
||||||
{
|
{
|
||||||
if (Light.LightSprite != null && (item.body == null || item.body.Enabled) && lightBrightness > 0.0f && IsOn)
|
if (Light.LightSprite != null && (item.body == null || item.body.Enabled) && lightBrightness > 0.0f && IsOn && Light.Enabled)
|
||||||
{
|
{
|
||||||
Vector2 origin = Light.LightSprite.Origin;
|
Vector2 origin = Light.LightSprite.Origin;
|
||||||
if ((Light.LightSpriteEffect & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally) { origin.X = Light.LightSprite.SourceRect.Width - origin.X; }
|
if ((Light.LightSpriteEffect & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally) { origin.X = Light.LightSprite.SourceRect.Width - origin.X; }
|
||||||
|
|||||||
+109
-13
@@ -14,12 +14,22 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
private GUIButton activateButton;
|
private GUIButton activateButton;
|
||||||
private GUIComponent inputInventoryHolder, outputInventoryHolder;
|
private GUIComponent inputInventoryHolder, outputInventoryHolder;
|
||||||
private GUICustomComponent inputInventoryOverlay;
|
|
||||||
|
|
||||||
private GUIComponent inSufficientPowerWarning;
|
private GUIComponent inSufficientPowerWarning;
|
||||||
|
|
||||||
private bool pendingState;
|
private bool pendingState;
|
||||||
|
|
||||||
|
private GUITextBlock infoArea;
|
||||||
|
|
||||||
|
[Serialize("DeconstructorDeconstruct", true)]
|
||||||
|
public string ActivateButtonText { get; set; }
|
||||||
|
|
||||||
|
[Serialize("", true)]
|
||||||
|
public string InfoText { get; set; }
|
||||||
|
|
||||||
|
[Serialize(0.0f, true)]
|
||||||
|
public float InfoAreaWidth { get; set; }
|
||||||
|
|
||||||
partial void InitProjSpecific(XElement element)
|
partial void InitProjSpecific(XElement element)
|
||||||
{
|
{
|
||||||
CreateGUI();
|
CreateGUI();
|
||||||
@@ -39,6 +49,12 @@ namespace Barotrauma.Items.Components
|
|||||||
RelativeSpacing = 0.08f
|
RelativeSpacing = 0.08f
|
||||||
};
|
};
|
||||||
|
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1f, 0.07f), paddedFrame.RectTransform), item.Name, font: GUI.SubHeadingFont)
|
||||||
|
{
|
||||||
|
TextAlignment = Alignment.Center,
|
||||||
|
AutoScaleHorizontal = true
|
||||||
|
};
|
||||||
|
|
||||||
var topFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.5f), paddedFrame.RectTransform), style: null);
|
var topFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.5f), paddedFrame.RectTransform), style: null);
|
||||||
|
|
||||||
// === INPUT LABEL === //
|
// === INPUT LABEL === //
|
||||||
@@ -55,22 +71,23 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
// === INPUT SLOTS === //
|
// === INPUT SLOTS === //
|
||||||
inputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(0.7f, 1f), inputArea.RectTransform), style: null);
|
inputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(0.7f, 1f), inputArea.RectTransform), style: null);
|
||||||
inputInventoryOverlay = new GUICustomComponent(new RectTransform(Vector2.One, inputInventoryHolder.RectTransform), DrawOverLay, null) { CanBeFocused = false };
|
new GUICustomComponent(new RectTransform(Vector2.One, inputInventoryHolder.RectTransform), DrawOverLay, null) { CanBeFocused = false };
|
||||||
|
|
||||||
// === ACTIVATE BUTTON === //
|
// === ACTIVATE BUTTON === //
|
||||||
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 0.7f), inputArea.RectTransform), childAnchor: Anchor.CenterLeft);
|
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 0.8f), inputArea.RectTransform), childAnchor: Anchor.CenterLeft);
|
||||||
activateButton = new GUIButton(new RectTransform(new Vector2(0.95f, 0.8f), buttonContainer.RectTransform), TextManager.Get("DeconstructorDeconstruct"), style: "DeviceButton")
|
activateButton = new GUIButton(new RectTransform(new Vector2(0.95f, 0.8f), buttonContainer.RectTransform), TextManager.Get("DeconstructorDeconstruct"), style: "DeviceButton")
|
||||||
{
|
{
|
||||||
TextBlock = { AutoScaleHorizontal = true },
|
TextBlock = { AutoScaleHorizontal = true },
|
||||||
OnClicked = ToggleActive
|
OnClicked = ToggleActive
|
||||||
};
|
};
|
||||||
inSufficientPowerWarning = new GUITextBlock(new RectTransform(Vector2.One, activateButton.RectTransform),
|
inSufficientPowerWarning = new GUITextBlock(new RectTransform(Vector2.One, activateButton.RectTransform),
|
||||||
TextManager.Get("DeconstructorNoPower"), textColor: GUI.Style.Orange, textAlignment: Alignment.Center, color: Color.Black, style: "OuterGlow")
|
TextManager.Get("DeconstructorNoPower"), textColor: GUI.Style.Orange, textAlignment: Alignment.Center, color: Color.Black, style: "OuterGlow", wrap: true)
|
||||||
{
|
{
|
||||||
HoverColor = Color.Black,
|
HoverColor = Color.Black,
|
||||||
IgnoreLayoutGroups = true,
|
IgnoreLayoutGroups = true,
|
||||||
Visible = false,
|
Visible = false,
|
||||||
CanBeFocused = false
|
CanBeFocused = false,
|
||||||
|
AutoScaleHorizontal = true
|
||||||
};
|
};
|
||||||
|
|
||||||
// === OUTPUT AREA === //
|
// === OUTPUT AREA === //
|
||||||
@@ -86,8 +103,70 @@ namespace Barotrauma.Items.Components
|
|||||||
outputLabel.RectTransform.Resize(new Point((int) outputLabel.Font.MeasureString(outputLabel.Text).X, outputLabel.RectTransform.Rect.Height));
|
outputLabel.RectTransform.Resize(new Point((int) outputLabel.Font.MeasureString(outputLabel.Text).X, outputLabel.RectTransform.Rect.Height));
|
||||||
new GUIFrame(new RectTransform(Vector2.One, outputLabelArea.RectTransform), style: "HorizontalLine");
|
new GUIFrame(new RectTransform(Vector2.One, outputLabelArea.RectTransform), style: "HorizontalLine");
|
||||||
|
|
||||||
// === OUTPUT SLOTS === //
|
var outputArea = new GUILayoutGroup(new RectTransform(new Vector2(1f, 1f), bottomFrame.RectTransform, Anchor.CenterLeft), childAnchor: Anchor.BottomLeft, isHorizontal: true) { Stretch = true, RelativeSpacing = 0.05f };
|
||||||
outputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(1f, 1f), bottomFrame.RectTransform, Anchor.CenterLeft), style: null);
|
|
||||||
|
// === OUTPUT SLOTS === //
|
||||||
|
outputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(1f - InfoAreaWidth, 1f), outputArea.RectTransform, Anchor.CenterLeft), style: null);
|
||||||
|
|
||||||
|
if (InfoAreaWidth >= 0.0f)
|
||||||
|
{
|
||||||
|
var infoAreaContainer = new GUILayoutGroup(new RectTransform(new Vector2(InfoAreaWidth, 0.8f), outputArea.RectTransform), childAnchor: Anchor.CenterLeft);
|
||||||
|
infoArea = new GUITextBlock(new RectTransform(new Vector2(0.95f, 0.95f), infoAreaContainer.RectTransform), string.Empty, wrap: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
ActivateButton.OnAddedToGUIUpdateList += (GUIComponent component) =>
|
||||||
|
{
|
||||||
|
activateButton.Enabled = true;
|
||||||
|
if (string.IsNullOrEmpty(InfoText))
|
||||||
|
{
|
||||||
|
infoArea.Text = string.Empty;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
infoArea.Text = TextManager.Get(InfoText, returnNull: true) ?? InfoText;
|
||||||
|
}
|
||||||
|
if (IsActive)
|
||||||
|
{
|
||||||
|
activateButton.Text = TextManager.Get("DeconstructorCancel");
|
||||||
|
infoArea.Text = string.Empty;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bool outputsFound = false;
|
||||||
|
foreach (var (inputItem, deconstructItem) in GetAvailableOutputs(checkRequiredOtherItems: true))
|
||||||
|
{
|
||||||
|
outputsFound = true;
|
||||||
|
if (!string.IsNullOrEmpty(deconstructItem.ActivateButtonText))
|
||||||
|
{
|
||||||
|
string buttonText = TextManager.Get(deconstructItem.ActivateButtonText, returnNull: true) ?? deconstructItem.ActivateButtonText;
|
||||||
|
string infoText = string.Empty;
|
||||||
|
if (!string.IsNullOrEmpty(deconstructItem.InfoText))
|
||||||
|
{
|
||||||
|
infoText = TextManager.Get(deconstructItem.InfoText, returnNull: true) ?? deconstructItem.InfoText;
|
||||||
|
}
|
||||||
|
inputItem.GetComponent<GeneticMaterial>()?.ModifyDeconstructInfo(this, ref buttonText, ref infoText);
|
||||||
|
activateButton.Text = buttonText;
|
||||||
|
if (infoArea != null)
|
||||||
|
{
|
||||||
|
infoArea.Text = infoText;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//no valid outputs found: check if we're missing some required items from the input slots and display a message about it if possible
|
||||||
|
if (!outputsFound && infoArea != null)
|
||||||
|
{
|
||||||
|
foreach (var (inputItem, deconstructItem) in GetAvailableOutputs(checkRequiredOtherItems: false))
|
||||||
|
{
|
||||||
|
if (deconstructItem.RequiredOtherItem.Any() && !string.IsNullOrEmpty(deconstructItem.InfoTextOnOtherItemMissing))
|
||||||
|
{
|
||||||
|
string missingItemName = TextManager.Get("entityname." + deconstructItem.RequiredOtherItem.First(), returnNull: true);
|
||||||
|
infoArea.Text = TextManager.GetWithVariable(deconstructItem.InfoTextOnOtherItemMissing, "[itemname]", missingItemName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
activateButton.Enabled = outputsFound;
|
||||||
|
activateButton.Text = TextManager.Get(ActivateButtonText);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Select(Character character)
|
public override bool Select(Character character)
|
||||||
@@ -126,13 +205,30 @@ namespace Barotrauma.Items.Components
|
|||||||
private void DrawOverLay(SpriteBatch spriteBatch, GUICustomComponent overlayComponent)
|
private void DrawOverLay(SpriteBatch spriteBatch, GUICustomComponent overlayComponent)
|
||||||
{
|
{
|
||||||
overlayComponent.RectTransform.SetAsLastChild();
|
overlayComponent.RectTransform.SetAsLastChild();
|
||||||
var lastSlot = inputContainer.Inventory.visualSlots.Last();
|
|
||||||
|
|
||||||
GUI.DrawRectangle(spriteBatch,
|
if (!(inputContainer?.Inventory?.visualSlots is { } visualSlots)) { return; }
|
||||||
new Rectangle(
|
|
||||||
lastSlot.Rect.X, lastSlot.Rect.Y + (int)(lastSlot.Rect.Height * (1.0f - progressState)),
|
if (DeconstructItemsSimultaneously)
|
||||||
lastSlot.Rect.Width, (int)(lastSlot.Rect.Height * progressState)),
|
{
|
||||||
GUI.Style.Green * 0.5f, isFilled: true);
|
for (int i = 0; i < InputContainer.Inventory.Capacity; i++)
|
||||||
|
{
|
||||||
|
if (InputContainer.Inventory.GetItemAt(i) == null) { continue; }
|
||||||
|
DrawProgressBar(InputContainer.Inventory.visualSlots[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DrawProgressBar(inputContainer.Inventory.visualSlots.Last());
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawProgressBar(VisualSlot slot)
|
||||||
|
{
|
||||||
|
GUI.DrawRectangle(spriteBatch,
|
||||||
|
new Rectangle(
|
||||||
|
slot.Rect.X, slot.Rect.Y + (int)(slot.Rect.Height * (1.0f - progressState)),
|
||||||
|
slot.Rect.Width, (int)(slot.Rect.Height * progressState)),
|
||||||
|
GUI.Style.Green * 0.5f, isFilled: true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private FabricationRecipe pendingFabricatedItem;
|
private FabricationRecipe pendingFabricatedItem;
|
||||||
|
|
||||||
private Pair<Rectangle, string> tooltip;
|
private (Rectangle area, string text)? tooltip;
|
||||||
|
|
||||||
private GUITextBlock requiredTimeBlock;
|
private GUITextBlock requiredTimeBlock;
|
||||||
|
|
||||||
@@ -255,19 +255,22 @@ namespace Barotrauma.Items.Components
|
|||||||
var item1 = c1.GUIComponent.UserData as FabricationRecipe;
|
var item1 = c1.GUIComponent.UserData as FabricationRecipe;
|
||||||
var item2 = c2.GUIComponent.UserData as FabricationRecipe;
|
var item2 = c2.GUIComponent.UserData as FabricationRecipe;
|
||||||
|
|
||||||
bool hasSkills1 = FabricationDegreeOfSuccess(character, item1.RequiredSkills) >= 0.5f;
|
int itemPlacement1 = FabricationDegreeOfSuccess(character, item1.RequiredSkills) >= 0.5f ? 0 : -1;
|
||||||
bool hasSkills2 = FabricationDegreeOfSuccess(character, item2.RequiredSkills) >= 0.5f;
|
int itemPlacement2 = FabricationDegreeOfSuccess(character, item2.RequiredSkills) >= 0.5f ? 0 : -1;
|
||||||
|
|
||||||
if (hasSkills1 != hasSkills2)
|
itemPlacement1 += item1.RequiresRecipe && !character.HasRecipeForItem(item1.TargetItem.Identifier) ? -2 : 0;
|
||||||
|
itemPlacement2 += item2.RequiresRecipe && !character.HasRecipeForItem(item2.TargetItem.Identifier) ? -2 : 0;
|
||||||
|
|
||||||
|
if (itemPlacement1 != itemPlacement2)
|
||||||
{
|
{
|
||||||
return hasSkills1 ? -1 : 1;
|
return itemPlacement1 > itemPlacement2 ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return string.Compare(item1.DisplayName, item2.DisplayName);
|
return string.Compare(item1.DisplayName, item2.DisplayName);
|
||||||
});
|
});
|
||||||
|
|
||||||
var sufficientSkillsText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), itemList.Content.RectTransform),
|
var sufficientSkillsText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), itemList.Content.RectTransform),
|
||||||
TextManager.Get("fabricatorsufficientskills", returnNull: true) ?? "Sufficient skills to fabricate", textColor: GUI.Style.Green, font: GUI.SubHeadingFont)
|
TextManager.Get("fabricatorsufficientskills"), textColor: GUI.Style.Green, font: GUI.SubHeadingFont)
|
||||||
{
|
{
|
||||||
AutoScaleHorizontal = true,
|
AutoScaleHorizontal = true,
|
||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
@@ -275,7 +278,7 @@ namespace Barotrauma.Items.Components
|
|||||||
sufficientSkillsText.RectTransform.SetAsFirstChild();
|
sufficientSkillsText.RectTransform.SetAsFirstChild();
|
||||||
|
|
||||||
var insufficientSkillsText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), itemList.Content.RectTransform),
|
var insufficientSkillsText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), itemList.Content.RectTransform),
|
||||||
TextManager.Get("fabricatorinsufficientskills", returnNull: true) ?? "Insufficient skills to fabricate", textColor: Color.Orange, font: GUI.SubHeadingFont)
|
TextManager.Get("fabricatorinsufficientskills"), textColor: Color.Orange, font: GUI.SubHeadingFont)
|
||||||
{
|
{
|
||||||
AutoScaleHorizontal = true,
|
AutoScaleHorizontal = true,
|
||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
@@ -285,6 +288,18 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
insufficientSkillsText.RectTransform.RepositionChildInHierarchy(itemList.Content.RectTransform.GetChildIndex(firstinSufficient.RectTransform));
|
insufficientSkillsText.RectTransform.RepositionChildInHierarchy(itemList.Content.RectTransform.GetChildIndex(firstinSufficient.RectTransform));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var requiresRecipeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), itemList.Content.RectTransform),
|
||||||
|
TextManager.Get("fabricatorrequiresrecipe"), textColor: Color.Red, font: GUI.SubHeadingFont)
|
||||||
|
{
|
||||||
|
AutoScaleHorizontal = true,
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
var firstRequiresRecipe = itemList.Content.Children.FirstOrDefault(c => c.UserData is FabricationRecipe fabricableItem && (fabricableItem.RequiresRecipe && !character.HasRecipeForItem(fabricableItem.TargetItem.Identifier)));
|
||||||
|
if (firstRequiresRecipe != null)
|
||||||
|
{
|
||||||
|
requiresRecipeText.RectTransform.RepositionChildInHierarchy(itemList.Content.RectTransform.GetChildIndex(firstRequiresRecipe.RectTransform));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawInputOverLay(SpriteBatch spriteBatch, GUICustomComponent overlayComponent)
|
private void DrawInputOverLay(SpriteBatch spriteBatch, GUICustomComponent overlayComponent)
|
||||||
@@ -297,6 +312,7 @@ namespace Barotrauma.Items.Components
|
|||||||
int slotIndex = 0;
|
int slotIndex = 0;
|
||||||
|
|
||||||
var missingItems = new List<FabricationRecipe.RequiredItem>();
|
var missingItems = new List<FabricationRecipe.RequiredItem>();
|
||||||
|
|
||||||
foreach (FabricationRecipe.RequiredItem requiredItem in targetItem.RequiredItems)
|
foreach (FabricationRecipe.RequiredItem requiredItem in targetItem.RequiredItems)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < requiredItem.Amount; i++)
|
for (int i = 0; i < requiredItem.Amount; i++)
|
||||||
@@ -308,6 +324,8 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
missingItems.Remove(missingItems.FirstOrDefault(mi => mi.ItemPrefabs.Contains(item.prefab)));
|
missingItems.Remove(missingItems.FirstOrDefault(mi => mi.ItemPrefabs.Contains(item.prefab)));
|
||||||
}
|
}
|
||||||
|
var missingCounts = missingItems.GroupBy(missingItem => missingItem).ToDictionary(x => x.Key, x => x.Count());
|
||||||
|
missingItems = missingItems.Distinct().ToList();
|
||||||
|
|
||||||
var availableIngredients = GetAvailableIngredients();
|
var availableIngredients = GetAvailableIngredients();
|
||||||
|
|
||||||
@@ -318,27 +336,27 @@ namespace Barotrauma.Items.Components
|
|||||||
slotIndex++;
|
slotIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
//highlight suitable ingredients in linked inventories
|
requiredItem.ItemPrefabs
|
||||||
foreach (Item item in availableIngredients)
|
.Where(requiredPrefab => availableIngredients.ContainsKey(requiredPrefab.Identifier))
|
||||||
{
|
.ForEach(requiredPrefab => {
|
||||||
if (item.ParentInventory != inputContainer.Inventory && IsItemValidIngredient(item, requiredItem))
|
var availablePrefabs = availableIngredients[requiredPrefab.Identifier];
|
||||||
{
|
|
||||||
int availableSlotIndex = item.ParentInventory.FindIndex(item);
|
availablePrefabs
|
||||||
//slots are null if the inventory has never been displayed
|
.Where(availablePrefab => availablePrefab.ParentInventory != inputContainer.Inventory)
|
||||||
//(linked item, but the UI is not set to be displayed at the same time)
|
.Where(availablePrefab => availablePrefab.ParentInventory.visualSlots != null) //slots are null if the inventory has never been displayed
|
||||||
if (item.ParentInventory.visualSlots != null)
|
.ForEach(availablePrefab => { //(linked item, but the UI is not set to be displayed at the same time)
|
||||||
{
|
int availableSlotIndex = availablePrefab.ParentInventory.FindIndex(availablePrefab);
|
||||||
if (item.ParentInventory.visualSlots[availableSlotIndex].HighlightTimer <= 0.0f)
|
|
||||||
{
|
if (availablePrefab.ParentInventory.visualSlots[availableSlotIndex].HighlightTimer <= 0.0f)
|
||||||
item.ParentInventory.visualSlots[availableSlotIndex].ShowBorderHighlight(GUI.Style.Green, 0.5f, 0.5f, 0.2f);
|
|
||||||
if (slotIndex < inputContainer.Capacity)
|
|
||||||
{
|
{
|
||||||
inputContainer.Inventory.visualSlots[slotIndex].ShowBorderHighlight(GUI.Style.Green, 0.5f, 0.5f, 0.2f);
|
availablePrefab.ParentInventory.visualSlots[availableSlotIndex].ShowBorderHighlight(GUI.Style.Green, 0.5f, 0.5f, 0.2f);
|
||||||
|
if (slotIndex < inputContainer.Capacity)
|
||||||
|
{
|
||||||
|
inputContainer.Inventory.visualSlots[slotIndex].ShowBorderHighlight(GUI.Style.Green, 0.5f, 0.5f, 0.2f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (slotIndex >= inputContainer.Capacity) { break; }
|
if (slotIndex >= inputContainer.Capacity) { break; }
|
||||||
|
|
||||||
@@ -350,11 +368,32 @@ namespace Barotrauma.Items.Components
|
|||||||
color: requiredItem.ItemPrefabs.First().InventoryIconColor * 0.3f,
|
color: requiredItem.ItemPrefabs.First().InventoryIconColor * 0.3f,
|
||||||
scale: Math.Min(slotRect.Width / itemIcon.size.X, slotRect.Height / itemIcon.size.Y));
|
scale: Math.Min(slotRect.Width / itemIcon.size.X, slotRect.Height / itemIcon.size.Y));
|
||||||
|
|
||||||
|
|
||||||
|
if (missingCounts[requiredItem] > 1)
|
||||||
|
{
|
||||||
|
Vector2 stackCountPos = new Vector2(slotRect.Right, slotRect.Bottom);
|
||||||
|
string stackCountText = "x" + missingCounts[requiredItem];
|
||||||
|
stackCountPos -= GUI.SmallFont.MeasureString(stackCountText) + new Vector2(4, 2);
|
||||||
|
GUI.SmallFont.DrawString(spriteBatch, stackCountText, stackCountPos + Vector2.One, Color.Black);
|
||||||
|
GUI.SmallFont.DrawString(spriteBatch, stackCountText, stackCountPos, Color.White);
|
||||||
|
}
|
||||||
|
|
||||||
if (requiredItem.UseCondition && requiredItem.MinCondition < 1.0f)
|
if (requiredItem.UseCondition && requiredItem.MinCondition < 1.0f)
|
||||||
{
|
{
|
||||||
GUI.DrawRectangle(spriteBatch, new Rectangle(slotRect.X, slotRect.Bottom - 8, slotRect.Width, 8), Color.Black * 0.8f, true);
|
DrawConditionBar(spriteBatch, requiredItem.MinCondition);
|
||||||
|
}
|
||||||
|
else if (requiredItem.MaxCondition < 1.0f)
|
||||||
|
{
|
||||||
|
DrawConditionBar(spriteBatch, requiredItem.MaxCondition);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawConditionBar(SpriteBatch sb, float condition)
|
||||||
|
{
|
||||||
|
int spacing = GUI.IntScale(4);
|
||||||
|
int height = GUI.IntScale(10);
|
||||||
|
GUI.DrawRectangle(spriteBatch, new Rectangle(slotRect.X + spacing, slotRect.Bottom - spacing - height, slotRect.Width - spacing * 2, height), Color.Black * 0.8f, true);
|
||||||
GUI.DrawRectangle(spriteBatch,
|
GUI.DrawRectangle(spriteBatch,
|
||||||
new Rectangle(slotRect.X, slotRect.Bottom - 8, (int)(slotRect.Width * requiredItem.MinCondition), 8),
|
new Rectangle(slotRect.X + spacing, slotRect.Bottom - spacing - height, (int)((slotRect.Width - spacing * 2) * condition), height),
|
||||||
GUI.Style.Green * 0.8f, true);
|
GUI.Style.Green * 0.8f, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,6 +406,10 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
toolTipText += " " + (int)Math.Round(requiredItem.MinCondition * 100) + "%";
|
toolTipText += " " + (int)Math.Round(requiredItem.MinCondition * 100) + "%";
|
||||||
}
|
}
|
||||||
|
else if(requiredItem.MaxCondition < 1.0f)
|
||||||
|
{
|
||||||
|
toolTipText += " 0-" + (int)Math.Round(requiredItem.MaxCondition * 100) + "%";
|
||||||
|
}
|
||||||
else if (requiredItem.MaxCondition <= 0.0f)
|
else if (requiredItem.MaxCondition <= 0.0f)
|
||||||
{
|
{
|
||||||
toolTipText = TextManager.GetWithVariable("displayname.emptyitem", "[itemname]", toolTipText);
|
toolTipText = TextManager.GetWithVariable("displayname.emptyitem", "[itemname]", toolTipText);
|
||||||
@@ -375,7 +418,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
toolTipText += '\n' + requiredItem.ItemPrefabs.First().Description;
|
toolTipText += '\n' + requiredItem.ItemPrefabs.First().Description;
|
||||||
}
|
}
|
||||||
tooltip = new Pair<Rectangle, string>(slotRect, toolTipText);
|
tooltip = (slotRect, toolTipText);
|
||||||
}
|
}
|
||||||
|
|
||||||
slotIndex++;
|
slotIndex++;
|
||||||
@@ -415,7 +458,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (tooltip != null)
|
if (tooltip != null)
|
||||||
{
|
{
|
||||||
GUIComponent.DrawToolTip(spriteBatch, tooltip.Second, tooltip.First);
|
GUIComponent.DrawToolTip(spriteBatch, tooltip.Value.text, tooltip.Value.area);
|
||||||
tooltip = null;
|
tooltip = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -435,6 +478,22 @@ namespace Barotrauma.Items.Components
|
|||||||
if (recipe?.DisplayName == null) { continue; }
|
if (recipe?.DisplayName == null) { continue; }
|
||||||
child.Visible = recipe.DisplayName.ToLower().Contains(filter);
|
child.Visible = recipe.DisplayName.ToLower().Contains(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go through the elements backwards, and disable the labels ("insufficient skills to fabricate", "recipe required...") if there's no items below them
|
||||||
|
bool recipeVisible = false;
|
||||||
|
foreach (GUIComponent child in itemList.Content.Children.Reverse())
|
||||||
|
{
|
||||||
|
if (!(child.UserData is FabricationRecipe recipe))
|
||||||
|
{
|
||||||
|
child.Visible = recipeVisible;
|
||||||
|
recipeVisible = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
recipeVisible = child.Visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
itemList.UpdateScrollBarSize();
|
itemList.UpdateScrollBarSize();
|
||||||
itemList.BarScroll = 0.0f;
|
itemList.BarScroll = 0.0f;
|
||||||
|
|
||||||
@@ -470,14 +529,30 @@ namespace Barotrauma.Items.Components
|
|||||||
};
|
};
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
string itemName = GetRecipeNameAndAmount(selectedItem);
|
||||||
|
string name = itemName;
|
||||||
|
|
||||||
|
float quality = GetFabricatedItemQuality(selectedItem, user);
|
||||||
|
if (quality > 0)
|
||||||
|
{
|
||||||
|
name = TextManager.GetWithVariable("itemname.quality" + (int)quality, "[itemname]", itemName + '\n', fallBackTag: "itemname.quality3");
|
||||||
|
}
|
||||||
|
|
||||||
var nameBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform),
|
var nameBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform),
|
||||||
GetRecipeNameAndAmount(selectedItem), textAlignment: Alignment.CenterLeft, textColor: Color.Aqua, font: GUI.SubHeadingFont)
|
name, textAlignment: Alignment.TopLeft, textColor: Color.Aqua, font: GUI.SubHeadingFont, parseRichText: true)
|
||||||
{
|
{
|
||||||
AutoScaleHorizontal = true
|
AutoScaleHorizontal = true
|
||||||
};
|
};
|
||||||
|
nameBlock.Padding = new Vector4(0, nameBlock.Padding.Y, GUI.IntScale(5), nameBlock.Padding.W);
|
||||||
nameBlock.Padding = new Vector4(0, nameBlock.Padding.Y, nameBlock.Padding.Z, nameBlock.Padding.W);
|
if (nameBlock.TextScale < 0.7f)
|
||||||
|
{
|
||||||
|
nameBlock.SetRichText(TextManager.GetWithVariable("itemname.quality" + (int)quality, "[itemname]", itemName, fallBackTag: "itemname.quality3"));
|
||||||
|
nameBlock.AutoScaleHorizontal = false;
|
||||||
|
nameBlock.TextScale = 0.7f;
|
||||||
|
nameBlock.Wrap = true;
|
||||||
|
nameBlock.SetTextPos();
|
||||||
|
nameBlock.RectTransform.MinSize = new Point(0, (int)(nameBlock.TextSize.Y * nameBlock.TextScale));
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(selectedItem.TargetItem.Description))
|
if (!string.IsNullOrWhiteSpace(selectedItem.TargetItem.Description))
|
||||||
{
|
{
|
||||||
@@ -489,6 +564,7 @@ namespace Barotrauma.Items.Components
|
|||||||
while (description.Rect.Height + nameBlock.Rect.Height > paddedFrame.Rect.Height)
|
while (description.Rect.Height + nameBlock.Rect.Height > paddedFrame.Rect.Height)
|
||||||
{
|
{
|
||||||
var lines = description.WrappedText.Split('\n');
|
var lines = description.WrappedText.Split('\n');
|
||||||
|
if (lines.Length <= 1) { break; }
|
||||||
var newString = string.Join('\n', lines.Take(lines.Length - 1));
|
var newString = string.Join('\n', lines.Take(lines.Length - 1));
|
||||||
description.Text = newString.Substring(0, newString.Length - 4) + "...";
|
description.Text = newString.Substring(0, newString.Length - 4) + "...";
|
||||||
description.CalculateHeightFromText();
|
description.CalculateHeightFromText();
|
||||||
@@ -598,10 +674,15 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
foreach (GUIComponent child in itemList.Content.Children)
|
foreach (GUIComponent child in itemList.Content.Children)
|
||||||
{
|
{
|
||||||
var itemPrefab = child.UserData as FabricationRecipe;
|
if (!(child.UserData is FabricationRecipe itemPrefab)) { continue; }
|
||||||
if (itemPrefab == null) continue;
|
|
||||||
|
|
||||||
bool canBeFabricated = CanBeFabricated(itemPrefab, availableIngredients);
|
if (itemPrefab != selectedItem &&
|
||||||
|
(child.Rect.Y > itemList.Rect.Bottom || child.Rect.Bottom < itemList.Rect.Y))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool canBeFabricated = CanBeFabricated(itemPrefab, availableIngredients, character);
|
||||||
if (itemPrefab == selectedItem)
|
if (itemPrefab == selectedItem)
|
||||||
{
|
{
|
||||||
activateButton.Enabled = canBeFabricated;
|
activateButton.Enabled = canBeFabricated;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -142,6 +142,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
partial void UpdateProjSpecific(float deltaTime)
|
partial void UpdateProjSpecific(float deltaTime)
|
||||||
{
|
{
|
||||||
|
float rotationRad = MathHelper.ToRadians(item.Rotation);
|
||||||
if (FlowPercentage < 0.0f)
|
if (FlowPercentage < 0.0f)
|
||||||
{
|
{
|
||||||
foreach (var (position, emitter) in pumpOutEmitters)
|
foreach (var (position, emitter) in pumpOutEmitters)
|
||||||
@@ -150,11 +151,12 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
//only emit "pump out" particles when underwater
|
//only emit "pump out" particles when underwater
|
||||||
Vector2 relativeParticlePos = (item.WorldRect.Location.ToVector2() + position * item.Scale) - item.WorldPosition;
|
Vector2 relativeParticlePos = (item.WorldRect.Location.ToVector2() + position * item.Scale) - item.WorldPosition;
|
||||||
float angle = 0.0f;
|
relativeParticlePos = MathUtils.RotatePoint(relativeParticlePos, item.FlippedX ? rotationRad : -rotationRad);
|
||||||
|
float angle = -rotationRad;
|
||||||
if (item.FlippedX)
|
if (item.FlippedX)
|
||||||
{
|
{
|
||||||
relativeParticlePos.X = -relativeParticlePos.X;
|
relativeParticlePos.X = -relativeParticlePos.X;
|
||||||
angle = MathHelper.Pi;
|
angle += MathHelper.Pi;
|
||||||
}
|
}
|
||||||
if (item.FlippedY)
|
if (item.FlippedY)
|
||||||
{
|
{
|
||||||
@@ -170,11 +172,12 @@ namespace Barotrauma.Items.Components
|
|||||||
foreach (var (position, emitter) in pumpInEmitters)
|
foreach (var (position, emitter) in pumpInEmitters)
|
||||||
{
|
{
|
||||||
Vector2 relativeParticlePos = (item.WorldRect.Location.ToVector2() + position * item.Scale) - item.WorldPosition;
|
Vector2 relativeParticlePos = (item.WorldRect.Location.ToVector2() + position * item.Scale) - item.WorldPosition;
|
||||||
float angle = 0.0f;
|
relativeParticlePos = MathUtils.RotatePoint(relativeParticlePos, item.FlippedX ? rotationRad : -rotationRad);
|
||||||
|
float angle = -rotationRad;
|
||||||
if (item.FlippedX)
|
if (item.FlippedX)
|
||||||
{
|
{
|
||||||
relativeParticlePos.X = -relativeParticlePos.X;
|
relativeParticlePos.X = -relativeParticlePos.X;
|
||||||
angle = MathHelper.Pi;
|
angle += MathHelper.Pi;
|
||||||
}
|
}
|
||||||
if (item.FlippedY)
|
if (item.FlippedY)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -134,6 +134,14 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private static string caveLabel;
|
private static string caveLabel;
|
||||||
|
|
||||||
|
|
||||||
|
[Serialize(false, false)]
|
||||||
|
public bool RightLayout
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
private bool AllowUsingMineralScanner =>
|
private bool AllowUsingMineralScanner =>
|
||||||
HasMineralScanner && !isConnectedToSteering;
|
HasMineralScanner && !isConnectedToSteering;
|
||||||
|
|
||||||
@@ -316,7 +324,7 @@ namespace Barotrauma.Items.Components
|
|||||||
"", warningColor, GUI.LargeFont, Alignment.Center);
|
"", warningColor, GUI.LargeFont, Alignment.Center);
|
||||||
|
|
||||||
// Setup layout for nav terminal
|
// Setup layout for nav terminal
|
||||||
if (isConnectedToSteering)
|
if (isConnectedToSteering || RightLayout)
|
||||||
{
|
{
|
||||||
controlContainer.RectTransform.RelativeOffset = controlBoxOffset;
|
controlContainer.RectTransform.RelativeOffset = controlBoxOffset;
|
||||||
controlContainer.RectTransform.SetPosition(Anchor.TopRight);
|
controlContainer.RectTransform.SetPosition(Anchor.TopRight);
|
||||||
@@ -446,11 +454,6 @@ namespace Barotrauma.Items.Components
|
|||||||
zoomSlider.BarScroll += PlayerInput.ScrollWheelSpeed / 1000.0f;
|
zoomSlider.BarScroll += PlayerInput.ScrollWheelSpeed / 1000.0f;
|
||||||
zoomSlider.OnMoved(zoomSlider, zoomSlider.BarScroll);
|
zoomSlider.OnMoved(zoomSlider, zoomSlider.BarScroll);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PlayerInput.KeyHit(InputType.Run))
|
|
||||||
{
|
|
||||||
SonarModeSwitch.OnClicked(SonarModeSwitch, null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float distort = 1.0f - item.Condition / item.MaxCondition;
|
float distort = 1.0f - item.Condition / item.MaxCondition;
|
||||||
@@ -885,7 +888,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
foreach (AITarget aiTarget in AITarget.List)
|
foreach (AITarget aiTarget in AITarget.List)
|
||||||
{
|
{
|
||||||
if (!aiTarget.Enabled) { continue; }
|
if (aiTarget.InDetectable) { continue; }
|
||||||
if (string.IsNullOrEmpty(aiTarget.SonarLabel) || aiTarget.SoundRange <= 0.0f) { continue; }
|
if (string.IsNullOrEmpty(aiTarget.SonarLabel) || aiTarget.SoundRange <= 0.0f) { continue; }
|
||||||
|
|
||||||
if (Vector2.DistanceSquared(aiTarget.WorldPosition, transducerCenter) < aiTarget.SoundRange * aiTarget.SoundRange)
|
if (Vector2.DistanceSquared(aiTarget.WorldPosition, transducerCenter) < aiTarget.SoundRange * aiTarget.SoundRange)
|
||||||
@@ -1239,7 +1242,7 @@ namespace Barotrauma.Items.Components
|
|||||||
foreach (AITarget aiTarget in AITarget.List)
|
foreach (AITarget aiTarget in AITarget.List)
|
||||||
{
|
{
|
||||||
float disruption = aiTarget.Entity is Character c ? c.Params.SonarDisruption : aiTarget.SonarDisruption;
|
float disruption = aiTarget.Entity is Character c ? c.Params.SonarDisruption : aiTarget.SonarDisruption;
|
||||||
if (disruption <= 0.0f || !aiTarget.Enabled) { continue; }
|
if (disruption <= 0.0f || aiTarget.InDetectable) { continue; }
|
||||||
float distSqr = Vector2.DistanceSquared(aiTarget.WorldPosition, pingSource);
|
float distSqr = Vector2.DistanceSquared(aiTarget.WorldPosition, pingSource);
|
||||||
if (distSqr > worldPingRadiusSqr) { continue; }
|
if (distSqr > worldPingRadiusSqr) { continue; }
|
||||||
float disruptionDist = (float)Math.Sqrt(distSqr);
|
float disruptionDist = (float)Math.Sqrt(distSqr);
|
||||||
@@ -1364,28 +1367,6 @@ namespace Barotrauma.Items.Components
|
|||||||
blipType : cell.IsDestructible ? BlipType.Destructible : BlipType.Default);
|
blipType : cell.IsDestructible ? BlipType.Destructible : BlipType.Default);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|
||||||
pingSource, transducerPos,
|
|
||||||
pingRadius, prevPingRadius,
|
|
||||||
100.0f, 1000.0f, range, pingStrength, passive);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Item item in Item.ItemList)
|
foreach (Item item in Item.ItemList)
|
||||||
@@ -1634,7 +1615,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
void CalculateDistance()
|
void CalculateDistance()
|
||||||
{
|
{
|
||||||
pathFinder ??= new PathFinder(WayPoint.WayPointList, indoorsSteering: false);
|
pathFinder ??= new PathFinder(WayPoint.WayPointList, false);
|
||||||
var path = pathFinder.FindPath(ConvertUnits.ToSimUnits(transducerPosition), ConvertUnits.ToSimUnits(worldPosition));
|
var path = pathFinder.FindPath(ConvertUnits.ToSimUnits(transducerPosition), ConvertUnits.ToSimUnits(worldPosition));
|
||||||
if (!path.Unreachable)
|
if (!path.Unreachable)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -888,6 +888,7 @@ namespace Barotrauma.Items.Components
|
|||||||
maintainPosOriginIndicator?.Remove();
|
maintainPosOriginIndicator?.Remove();
|
||||||
steeringIndicator?.Remove();
|
steeringIndicator?.Remove();
|
||||||
enterOutpostPrompt?.Close();
|
enterOutpostPrompt?.Close();
|
||||||
|
pathFinder = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ namespace Barotrauma.Items.Components
|
|||||||
var chargeText = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1), textArea.RectTransform, Anchor.CenterRight),
|
var chargeText = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1), textArea.RectTransform, Anchor.CenterRight),
|
||||||
"", textColor: GUI.Style.TextColor, font: GUI.Font, textAlignment: Alignment.CenterRight)
|
"", textColor: GUI.Style.TextColor, font: GUI.Font, textAlignment: Alignment.CenterRight)
|
||||||
{
|
{
|
||||||
TextGetter = () => $"{(int)charge}/{(int)capacity} {kWmin} ({((int)MathUtils.Percentage(charge, capacity)).ToString()} %)"
|
TextGetter = () => $"{(int)Math.Round(charge)}/{(int)capacity} {kWmin} ({(int)Math.Round(MathUtils.Percentage(charge, capacity))} %)"
|
||||||
};
|
};
|
||||||
if (chargeText.TextSize.X > chargeText.Rect.Width) { chargeText.Font = GUI.SmallFont; }
|
if (chargeText.TextSize.X > chargeText.Rect.Width) { chargeText.Font = GUI.SmallFont; }
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
|
||||||
|
namespace Barotrauma.Items.Components
|
||||||
|
{
|
||||||
|
partial class Quality : ItemComponent
|
||||||
|
{
|
||||||
|
public override void AddTooltipInfo(ref string name, ref string description)
|
||||||
|
{
|
||||||
|
foreach (var statValue in statValues)
|
||||||
|
{
|
||||||
|
int roundedValue = (int)Math.Round(statValue.Value * qualityLevel * 100);
|
||||||
|
if (roundedValue == 0) { return; }
|
||||||
|
string colorStr = XMLExtensions.ColorToString(GUI.Style.Green);
|
||||||
|
description += $"\n ‖color:{colorStr}‖{roundedValue.ToString("+0;-#")}%‖color:end‖ {TextManager.Get("qualitystattypenames." + statValue.Key.ToString(), true) ?? statValue.Key.ToString()}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
|
namespace Barotrauma.Items.Components
|
||||||
|
{
|
||||||
|
partial class RemoteController : ItemComponent
|
||||||
|
{
|
||||||
|
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||||
|
{
|
||||||
|
currentTarget?.DrawHUD(spriteBatch, Screen.Selected.Cam, character);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
||||||
|
{
|
||||||
|
currentTarget?.UpdateHUD(cam, character,deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void AddToGUIUpdateList(int order = 0)
|
||||||
|
{
|
||||||
|
currentTarget?.AddToGUIUpdateList(order: -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,16 +15,23 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
public GUIButton SabotageButton { get; private set; }
|
public GUIButton SabotageButton { get; private set; }
|
||||||
|
|
||||||
|
public GUIButton TinkerButton { get; private set; }
|
||||||
|
|
||||||
private GUIProgressBar progressBar;
|
private GUIProgressBar progressBar;
|
||||||
|
|
||||||
private List<ParticleEmitter> particleEmitters = new List<ParticleEmitter>();
|
private GUITextBlock progressBarOverlayText;
|
||||||
|
|
||||||
|
private GUILayoutGroup extraButtonContainer;
|
||||||
|
|
||||||
|
private readonly List<ParticleEmitter> particleEmitters = new List<ParticleEmitter>();
|
||||||
//the corresponding particle emitter is active when the condition is within this range
|
//the corresponding particle emitter is active when the condition is within this range
|
||||||
private List<Vector2> particleEmitterConditionRanges = new List<Vector2>();
|
private readonly List<Vector2> particleEmitterConditionRanges = new List<Vector2>();
|
||||||
|
|
||||||
private SoundChannel repairSoundChannel;
|
private SoundChannel repairSoundChannel;
|
||||||
|
|
||||||
private string repairButtonText, repairingText;
|
private string repairButtonText, repairingText;
|
||||||
private string sabotageButtonText, sabotagingText;
|
private string sabotageButtonText, sabotagingText;
|
||||||
|
private string tinkerButtonText, tinkeringText;
|
||||||
|
|
||||||
private FixActions requestStartFixAction;
|
private FixActions requestStartFixAction;
|
||||||
|
|
||||||
@@ -45,8 +52,24 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
public override bool ShouldDrawHUD(Character character)
|
public override bool ShouldDrawHUD(Character character)
|
||||||
{
|
{
|
||||||
if (!HasRequiredItems(character, false) || character.SelectedConstruction != item) return false;
|
if (!HasRequiredItems(character, false) || character.SelectedConstruction != item) { return false; }
|
||||||
return item.ConditionPercentage < RepairThreshold || character.IsTraitor && item.ConditionPercentage > MinSabotageCondition || (CurrentFixer == character && (!item.IsFullCondition || (character.IsTraitor && item.ConditionPercentage > MinSabotageCondition)));
|
if (character.IsTraitor && item.ConditionPercentage > MinSabotageCondition) { return true; }
|
||||||
|
|
||||||
|
float maxRepairConditionMultiplier = GetMaxRepairConditionMultiplier(character);
|
||||||
|
if (item.Condition / maxRepairConditionMultiplier < RepairThreshold) { return true; }
|
||||||
|
|
||||||
|
if (CurrentFixer == character)
|
||||||
|
{
|
||||||
|
float condition = item.Condition / item.MaxRepairConditionMultiplier;
|
||||||
|
float maxCondition = item.MaxCondition / item.MaxRepairConditionMultiplier;
|
||||||
|
if (condition < maxCondition * maxRepairConditionMultiplier)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (IsTinkerable(character)) { return true; }
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void InitProjSpecific(XElement element)
|
partial void InitProjSpecific(XElement element)
|
||||||
@@ -85,7 +108,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateGUI()
|
protected override void CreateGUI()
|
||||||
{
|
{
|
||||||
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 0.75f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter)
|
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 0.75f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter)
|
||||||
{
|
{
|
||||||
@@ -120,6 +143,11 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
progressBar = new GUIProgressBar(new RectTransform(new Vector2(0.6f, 1.0f), progressBarHolder.RectTransform),
|
progressBar = new GUIProgressBar(new RectTransform(new Vector2(0.6f, 1.0f), progressBarHolder.RectTransform),
|
||||||
color: GUI.Style.Green, barSize: 0.0f, style: "DeviceProgressBar");
|
color: GUI.Style.Green, barSize: 0.0f, style: "DeviceProgressBar");
|
||||||
|
progressBarOverlayText = new GUITextBlock(new RectTransform(Vector2.One, progressBar.RectTransform), string.Empty, font: GUI.SubHeadingFont, textAlignment: Alignment.Center)
|
||||||
|
{
|
||||||
|
IgnoreLayoutGroups = true
|
||||||
|
};
|
||||||
|
|
||||||
repairButtonText = TextManager.Get("RepairButton");
|
repairButtonText = TextManager.Get("RepairButton");
|
||||||
repairingText = TextManager.Get("Repairing");
|
repairingText = TextManager.Get("Repairing");
|
||||||
RepairButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1.0f), progressBarHolder.RectTransform, Anchor.TopCenter), repairButtonText)
|
RepairButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1.0f), progressBarHolder.RectTransform, Anchor.TopCenter), repairButtonText)
|
||||||
@@ -135,9 +163,16 @@ namespace Barotrauma.Items.Components
|
|||||||
progressBarHolder.RectTransform.MinSize = RepairButton.RectTransform.MinSize;
|
progressBarHolder.RectTransform.MinSize = RepairButton.RectTransform.MinSize;
|
||||||
RepairButton.RectTransform.MinSize = new Point((int)(RepairButton.TextBlock.TextSize.X * 1.2f), RepairButton.RectTransform.MinSize.Y);
|
RepairButton.RectTransform.MinSize = new Point((int)(RepairButton.TextBlock.TextSize.X * 1.2f), RepairButton.RectTransform.MinSize.Y);
|
||||||
|
|
||||||
|
extraButtonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), paddedFrame.RectTransform), isHorizontal: true)
|
||||||
|
{
|
||||||
|
IgnoreLayoutGroups = true,
|
||||||
|
Stretch = true,
|
||||||
|
AbsoluteSpacing = GUI.IntScale(5)
|
||||||
|
};
|
||||||
|
|
||||||
sabotageButtonText = TextManager.Get("SabotageButton");
|
sabotageButtonText = TextManager.Get("SabotageButton");
|
||||||
sabotagingText = TextManager.Get("Sabotaging");
|
sabotagingText = TextManager.Get("Sabotaging");
|
||||||
SabotageButton = new GUIButton(new RectTransform(new Vector2(0.8f, 0.15f), paddedFrame.RectTransform, Anchor.BottomCenter), sabotageButtonText, style: "GUIButtonSmall")
|
SabotageButton = new GUIButton(new RectTransform(Vector2.One, extraButtonContainer.RectTransform), sabotageButtonText, style: "GUIButtonSmall")
|
||||||
{
|
{
|
||||||
IgnoreLayoutGroups = true,
|
IgnoreLayoutGroups = true,
|
||||||
Visible = false,
|
Visible = false,
|
||||||
@@ -148,6 +183,22 @@ namespace Barotrauma.Items.Components
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
tinkerButtonText = TextManager.Get("TinkerButton", returnNull: true) ?? "Tinker";
|
||||||
|
tinkeringText = TextManager.Get("Tinkering", returnNull: true) ?? "Tinkering";
|
||||||
|
TinkerButton = new GUIButton(new RectTransform(Vector2.One, extraButtonContainer.RectTransform), tinkerButtonText, style: "GUIButtonSmall")
|
||||||
|
{
|
||||||
|
IgnoreLayoutGroups = true,
|
||||||
|
Visible = false,
|
||||||
|
OnClicked = (btn, obj) =>
|
||||||
|
{
|
||||||
|
requestStartFixAction = FixActions.Tinker;
|
||||||
|
item.CreateClientEvent(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
extraButtonContainer.RectTransform.MinSize = new Point(0, SabotageButton.RectTransform.MinSize.Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void UpdateProjSpecific(float deltaTime)
|
partial void UpdateProjSpecific(float deltaTime)
|
||||||
@@ -176,6 +227,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
case FixActions.Repair:
|
case FixActions.Repair:
|
||||||
case FixActions.Sabotage:
|
case FixActions.Sabotage:
|
||||||
|
case FixActions.Tinker:
|
||||||
StartRepairing(Character.Controlled, requestStartFixAction);
|
StartRepairing(Character.Controlled, requestStartFixAction);
|
||||||
requestStartFixAction = FixActions.None;
|
requestStartFixAction = FixActions.None;
|
||||||
break;
|
break;
|
||||||
@@ -211,10 +263,24 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
IsActive = true;
|
IsActive = true;
|
||||||
|
|
||||||
progressBar.BarSize = item.Condition / item.MaxCondition;
|
float defaultMaxCondition = (item.MaxCondition / item.MaxRepairConditionMultiplier);
|
||||||
|
|
||||||
|
progressBar.BarSize = item.Condition / defaultMaxCondition;
|
||||||
progressBar.Color = ToolBox.GradientLerp(progressBar.BarSize, GUI.Style.Red, GUI.Style.Orange, GUI.Style.Green);
|
progressBar.Color = ToolBox.GradientLerp(progressBar.BarSize, GUI.Style.Red, GUI.Style.Orange, GUI.Style.Green);
|
||||||
|
|
||||||
RepairButton.Enabled = (currentFixerAction == FixActions.None || (CurrentFixer == character && currentFixerAction != FixActions.Repair)) && !item.IsFullCondition;
|
if (item.Condition > defaultMaxCondition)
|
||||||
|
{
|
||||||
|
float extraCondition = item.MaxCondition * (item.MaxRepairConditionMultiplier - 1.0f);
|
||||||
|
progressBar.Color = ToolBox.GradientLerp((item.Condition - defaultMaxCondition) / extraCondition, GUI.Style.ColorReputationHigh, GUI.Style.ColorReputationVeryHigh);
|
||||||
|
progressBarOverlayText.Visible = true;
|
||||||
|
progressBarOverlayText.Text = $"{(int)Math.Round((item.Condition / defaultMaxCondition) * 100)}%";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
progressBarOverlayText.Visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
RepairButton.Enabled = (currentFixerAction == FixActions.None || (CurrentFixer == character && currentFixerAction != FixActions.Repair)) && !item.IsFullCondition && item.ConditionPercentage < RepairThreshold;
|
||||||
RepairButton.Text = (currentFixerAction == FixActions.None || CurrentFixer != character || currentFixerAction != FixActions.Repair) ?
|
RepairButton.Text = (currentFixerAction == FixActions.None || CurrentFixer != character || currentFixerAction != FixActions.Repair) ?
|
||||||
repairButtonText :
|
repairButtonText :
|
||||||
repairingText + new string('.', ((int)(Timing.TotalTime * 2.0f) % 3) + 1);
|
repairingText + new string('.', ((int)(Timing.TotalTime * 2.0f) % 3) + 1);
|
||||||
@@ -226,7 +292,18 @@ namespace Barotrauma.Items.Components
|
|||||||
sabotageButtonText :
|
sabotageButtonText :
|
||||||
sabotagingText + new string('.', ((int)(Timing.TotalTime * 2.0f) % 3) + 1);
|
sabotagingText + new string('.', ((int)(Timing.TotalTime * 2.0f) % 3) + 1);
|
||||||
|
|
||||||
|
TinkerButton.Visible = IsTinkerable(character);
|
||||||
|
TinkerButton.IgnoreLayoutGroups = !TinkerButton.Visible;
|
||||||
|
TinkerButton.Enabled = (currentFixerAction == FixActions.None || (CurrentFixer == character && currentFixerAction != FixActions.Tinker)) && CanTinker(character);
|
||||||
|
TinkerButton.Text = (currentFixerAction == FixActions.None || CurrentFixer != character || currentFixerAction != FixActions.Tinker) ?
|
||||||
|
tinkerButtonText :
|
||||||
|
tinkeringText + 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");
|
System.Diagnostics.Debug.Assert(GuiFrame.GetChild(0) is GUILayoutGroup, "Repair UI hierarchy has changed, could not find skill texts");
|
||||||
|
|
||||||
|
extraButtonContainer.Visible = SabotageButton.Visible || TinkerButton.Visible;
|
||||||
|
extraButtonContainer.IgnoreLayoutGroups = !extraButtonContainer.Visible;
|
||||||
|
|
||||||
foreach (GUIComponent c in GuiFrame.GetChild(0).Children)
|
foreach (GUIComponent c in GuiFrame.GetChild(0).Children)
|
||||||
{
|
{
|
||||||
if (!(c.UserData is Skill skill)) continue;
|
if (!(c.UserData is Skill skill)) continue;
|
||||||
@@ -278,9 +355,12 @@ namespace Barotrauma.Items.Components
|
|||||||
deteriorationTimer = msg.ReadSingle();
|
deteriorationTimer = msg.ReadSingle();
|
||||||
deteriorateAlwaysResetTimer = msg.ReadSingle();
|
deteriorateAlwaysResetTimer = msg.ReadSingle();
|
||||||
DeteriorateAlways = msg.ReadBoolean();
|
DeteriorateAlways = msg.ReadBoolean();
|
||||||
|
tinkeringDuration = msg.ReadSingle();
|
||||||
|
tinkeringStrength = msg.ReadSingle();
|
||||||
ushort currentFixerID = msg.ReadUInt16();
|
ushort currentFixerID = msg.ReadUInt16();
|
||||||
currentFixerAction = (FixActions)msg.ReadRangedInteger(0, 2);
|
currentFixerAction = (FixActions)msg.ReadRangedInteger(0, 2);
|
||||||
CurrentFixer = currentFixerID != 0 ? Entity.FindEntityByID(currentFixerID) as Character : null;
|
CurrentFixer = currentFixerID != 0 ? Entity.FindEntityByID(currentFixerID) as Character : null;
|
||||||
|
item.MaxRepairConditionMultiplier = GetMaxRepairConditionMultiplier(CurrentFixer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
||||||
|
|||||||
@@ -31,6 +31,9 @@ namespace Barotrauma.Items.Components
|
|||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Serialize("0.5,0.5)", false)]
|
||||||
|
public Vector2 Origin { get; set; } = new Vector2(0.5f, 0.5f);
|
||||||
|
|
||||||
public Vector2 DrawSize
|
public Vector2 DrawSize
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -57,7 +60,6 @@ namespace Barotrauma.Items.Components
|
|||||||
sourcePos = sourceLimb.body.DrawPosition;
|
sourcePos = sourceLimb.body.DrawPosition;
|
||||||
}
|
}
|
||||||
return sourcePos;
|
return sourcePos;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void InitProjSpecific(XElement element)
|
partial void InitProjSpecific(XElement element)
|
||||||
@@ -81,13 +83,15 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
|
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
|
||||||
{
|
{
|
||||||
if (target == null) { return; }
|
if (target == null || target.Removed) { return; }
|
||||||
|
if (target.ParentInventory != null) { return; }
|
||||||
|
|
||||||
Vector2 startPos = GetSourcePos();
|
Vector2 startPos = GetSourcePos();
|
||||||
startPos.Y = -startPos.Y;
|
startPos.Y = -startPos.Y;
|
||||||
if (source is Item sourceItem)
|
if (source is Item sourceItem)
|
||||||
{
|
{
|
||||||
var turret = sourceItem?.GetComponent<Turret>();
|
var turret = sourceItem.GetComponent<Turret>();
|
||||||
|
var weapon = sourceItem.GetComponent<RangedWeapon>();
|
||||||
if (turret != null)
|
if (turret != null)
|
||||||
{
|
{
|
||||||
startPos = new Vector2(sourceItem.WorldRect.X + turret.TransformedBarrelPos.X, -(sourceItem.WorldRect.Y - turret.TransformedBarrelPos.Y));
|
startPos = new Vector2(sourceItem.WorldRect.X + turret.TransformedBarrelPos.X, -(sourceItem.WorldRect.Y - turret.TransformedBarrelPos.Y));
|
||||||
@@ -96,8 +100,21 @@ namespace Barotrauma.Items.Components
|
|||||||
startPos += new Vector2((float)Math.Cos(turret.Rotation), (float)Math.Sin(turret.Rotation)) * turret.BarrelSprite.size.Y * turret.BarrelSprite.RelativeOrigin.Y * item.Scale * 0.9f;
|
startPos += new Vector2((float)Math.Cos(turret.Rotation), (float)Math.Sin(turret.Rotation)) * turret.BarrelSprite.size.Y * turret.BarrelSprite.RelativeOrigin.Y * item.Scale * 0.9f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (weapon != null)
|
||||||
|
{
|
||||||
|
Vector2 barrelPos = FarseerPhysics.ConvertUnits.ToDisplayUnits(weapon.TransformedBarrelPos);
|
||||||
|
barrelPos.Y = -barrelPos.Y;
|
||||||
|
startPos += barrelPos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Vector2 endPos = new Vector2(target.DrawPosition.X, -target.DrawPosition.Y);
|
Vector2 endPos = new Vector2(target.DrawPosition.X, target.DrawPosition.Y);
|
||||||
|
Vector2 flippedPos = target.Sprite.size * target.Scale * (Origin - new Vector2(0.5f));
|
||||||
|
if (target.body.Dir < 0.0f)
|
||||||
|
{
|
||||||
|
flippedPos.X = -flippedPos.X;
|
||||||
|
}
|
||||||
|
endPos += Vector2.Transform(flippedPos, Matrix.CreateRotationZ(target.body.Rotation));
|
||||||
|
endPos.Y = -endPos.Y;
|
||||||
|
|
||||||
if (Snapped)
|
if (Snapped)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using Barotrauma.Networking;
|
||||||
|
|
||||||
|
namespace Barotrauma.Items.Components
|
||||||
|
{
|
||||||
|
partial class Scanner : ItemComponent, IServerSerializable
|
||||||
|
{
|
||||||
|
partial void UpdateProjSpecific()
|
||||||
|
{
|
||||||
|
if (Holdable != null && Holdable.Attached && (AlwaysDisplayProgressBar || DisplayProgressBar) && !IsScanCompleted)
|
||||||
|
{
|
||||||
|
Character.Controlled?.UpdateHUDProgressBar(this,
|
||||||
|
item.WorldPosition,
|
||||||
|
ScanTimer / ScanDuration,
|
||||||
|
GUI.Style.Red, GUI.Style.Green,
|
||||||
|
textTag: "progressbar.scanning");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||||
|
{
|
||||||
|
bool wasScanCompletedPreviously = IsScanCompleted;
|
||||||
|
scanTimer = msg.ReadSingle();
|
||||||
|
if (!wasScanCompletedPreviously && IsScanCompleted)
|
||||||
|
{
|
||||||
|
OnScanCompleted?.Invoke(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
using Barotrauma.Extensions;
|
||||||
|
using Barotrauma.Networking;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
|
||||||
|
namespace Barotrauma.Items.Components
|
||||||
|
{
|
||||||
|
partial class ButtonTerminal : ItemComponent, IClientSerializable, IServerSerializable
|
||||||
|
{
|
||||||
|
private string[] terminalButtonStyles;
|
||||||
|
private GUIFrame containerHolder;
|
||||||
|
private GUIImage containerIndicator;
|
||||||
|
private GUIComponentStyle indicatorStyleRed, indicatorStyleGreen;
|
||||||
|
|
||||||
|
partial void InitProjSpecific(XElement element)
|
||||||
|
{
|
||||||
|
terminalButtonStyles = new string[RequiredSignalCount];
|
||||||
|
int i = 0;
|
||||||
|
foreach (var childElement in element.GetChildElements("TerminalButton"))
|
||||||
|
{
|
||||||
|
string style = childElement.GetAttributeString("style", null);
|
||||||
|
if (style == null) { continue; }
|
||||||
|
terminalButtonStyles[i++] = style;
|
||||||
|
}
|
||||||
|
indicatorStyleRed = GUI.Style.GetComponentStyle("IndicatorLightRed");
|
||||||
|
indicatorStyleGreen = GUI.Style.GetComponentStyle("IndicatorLightGreen");
|
||||||
|
CreateGUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void CreateGUI()
|
||||||
|
{
|
||||||
|
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.8f), GuiFrame.RectTransform, Anchor.Center), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||||
|
{
|
||||||
|
Stretch = true,
|
||||||
|
RelativeSpacing = 0.08f
|
||||||
|
};
|
||||||
|
paddedFrame.OnAddedToGUIUpdateList += (component) =>
|
||||||
|
{
|
||||||
|
bool buttonsEnabled = AllowUsingButtons;
|
||||||
|
foreach (var child in component.Children)
|
||||||
|
{
|
||||||
|
if (!(child is GUIButton)) { continue; }
|
||||||
|
if (!(child.UserData is int)) { continue; }
|
||||||
|
child.Enabled = buttonsEnabled;
|
||||||
|
child.Children.ForEach(c => c.Enabled = buttonsEnabled);
|
||||||
|
}
|
||||||
|
bool itemsContained = Container.Inventory.AllItems.Any();
|
||||||
|
if (itemsContained)
|
||||||
|
{
|
||||||
|
var indicatorStyle = buttonsEnabled ? indicatorStyleGreen : indicatorStyleRed;
|
||||||
|
if (containerIndicator.Style != indicatorStyle)
|
||||||
|
{
|
||||||
|
containerIndicator.ApplyStyle(indicatorStyle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
containerIndicator.OverrideState = itemsContained ? GUIComponent.ComponentState.Selected : GUIComponent.ComponentState.None;
|
||||||
|
};
|
||||||
|
|
||||||
|
float x = 1.0f / (1 + RequiredSignalCount);
|
||||||
|
float y = Math.Min((x * paddedFrame.Rect.Width) / paddedFrame.Rect.Height, 0.5f);
|
||||||
|
Vector2 relativeSize = new Vector2(x, y);
|
||||||
|
|
||||||
|
var containerSection = new GUIFrame(new RectTransform(new Vector2(x, 1.0f), paddedFrame.RectTransform), style: null);
|
||||||
|
var containerSlot = new GUIFrame(new RectTransform(new Vector2(1.0f, y), containerSection.RectTransform, anchor: Anchor.Center), style: null);
|
||||||
|
containerHolder = new GUIFrame(new RectTransform(new Vector2(1f, 1.2f), containerSlot.RectTransform, Anchor.BottomCenter), style: null);
|
||||||
|
containerIndicator = new GUIImage(new RectTransform(new Vector2(0.5f, 0.5f * (1.0f - y)), containerSection.RectTransform, anchor: Anchor.BottomCenter),
|
||||||
|
style: "IndicatorLightRed", scaleToFit: true);
|
||||||
|
|
||||||
|
for (int i = 0; i < RequiredSignalCount; i++)
|
||||||
|
{
|
||||||
|
var button = new GUIButton(new RectTransform(relativeSize, paddedFrame.RectTransform), style: null)
|
||||||
|
{
|
||||||
|
UserData = i,
|
||||||
|
OnClicked = (button, userData) =>
|
||||||
|
{
|
||||||
|
if (GameMain.IsSingleplayer)
|
||||||
|
{
|
||||||
|
SendSignal((int)userData);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item.CreateClientEvent(this, new object[] { userData });
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var image = new GUIImage(new RectTransform(Vector2.One, button.RectTransform), terminalButtonStyles[i], scaleToFit: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnResolutionChanged()
|
||||||
|
{
|
||||||
|
base.OnResolutionChanged();
|
||||||
|
OnItemLoadedProjSpecific();
|
||||||
|
}
|
||||||
|
|
||||||
|
partial void OnItemLoadedProjSpecific()
|
||||||
|
{
|
||||||
|
Container.AllowUIOverlap = true;
|
||||||
|
Container.Inventory.RectTransform = containerHolder.RectTransform;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
||||||
|
{
|
||||||
|
Write(msg, extraData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||||
|
{
|
||||||
|
SendSignal(msg.ReadRangedInteger(0, Signals.Length - 1), isServerMessage: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -54,6 +54,11 @@ namespace Barotrauma.Items.Components
|
|||||||
if (wireComponent != null)
|
if (wireComponent != null)
|
||||||
{
|
{
|
||||||
equippedWire = wireComponent;
|
equippedWire = wireComponent;
|
||||||
|
var connectedEnd = equippedWire.OtherConnection(null);
|
||||||
|
if (connectedEnd?.Item.Submarine != null && panel.Item.Submarine != connectedEnd.Item.Submarine)
|
||||||
|
{
|
||||||
|
equippedWire = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,11 +88,6 @@ namespace Barotrauma.Items.Components
|
|||||||
return character == Character.Controlled && character == user && character.SelectedConstruction == item;
|
return character == Character.Controlled && character == user && character.SelectedConstruction == item;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void AddToGUIUpdateList()
|
|
||||||
{
|
|
||||||
GuiFrame?.AddToGUIUpdateList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
||||||
{
|
{
|
||||||
if (character != Character.Controlled || character != user || character.SelectedConstruction != item) { return; }
|
if (character != Character.Controlled || character != user || character.SelectedConstruction != item) { return; }
|
||||||
|
|||||||
@@ -63,11 +63,11 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
OutputValue = input;
|
OutputValue = input;
|
||||||
ShowOnDisplay(input);
|
ShowOnDisplay(input, addToHistory: true);
|
||||||
item.SendSignal(input, "signal_out");
|
item.SendSignal(input, "signal_out");
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void ShowOnDisplay(string input, bool addToHistory = true)
|
partial void ShowOnDisplay(string input, bool addToHistory)
|
||||||
{
|
{
|
||||||
if (addToHistory)
|
if (addToHistory)
|
||||||
{
|
{
|
||||||
@@ -85,7 +85,7 @@ namespace Barotrauma.Items.Components
|
|||||||
GUITextBlock newBlock = new GUITextBlock(
|
GUITextBlock newBlock = new GUITextBlock(
|
||||||
new RectTransform(new Vector2(1, 0), historyBox.Content.RectTransform, anchor: Anchor.TopCenter),
|
new RectTransform(new Vector2(1, 0), historyBox.Content.RectTransform, anchor: Anchor.TopCenter),
|
||||||
"> " + input,
|
"> " + input,
|
||||||
textColor: Color.LimeGreen, wrap: true)
|
textColor: Color.LimeGreen, wrap: true, font: UseMonospaceFont ? GUI.MonospacedFont : GUI.GlobalFont)
|
||||||
{
|
{
|
||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
@@ -118,9 +118,9 @@ namespace Barotrauma.Items.Components
|
|||||||
// This method is overrided instead of the UpdateHUD method because this ensures the input box is selected
|
// This method is overrided instead of the UpdateHUD method because this ensures the input box is selected
|
||||||
// even when the terminal component is selected for the very first time. Doing the input box selection in the
|
// even when the terminal component is selected for the very first time. Doing the input box selection in the
|
||||||
// UpdateHUD method only selects the input box on every terminal selection except for the very first time.
|
// UpdateHUD method only selects the input box on every terminal selection except for the very first time.
|
||||||
public override void AddToGUIUpdateList()
|
public override void AddToGUIUpdateList(int order = 0)
|
||||||
{
|
{
|
||||||
base.AddToGUIUpdateList();
|
base.AddToGUIUpdateList(order: order);
|
||||||
if (shouldSelectInputBox)
|
if (shouldSelectInputBox)
|
||||||
{
|
{
|
||||||
inputBox.Select();
|
inputBox.Select();
|
||||||
|
|||||||
@@ -39,6 +39,34 @@ namespace Barotrauma.Items.Components
|
|||||||
private set;
|
private set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Serialize(false, false)]
|
||||||
|
public bool ThermalGoggles
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serialize(true, false)]
|
||||||
|
public bool ShowDeadCharacters
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serialize(true, false)]
|
||||||
|
public bool ShowTexts
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serialize("72,119,72,120", false)]
|
||||||
|
public Color OverlayColor
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
private readonly List<Character> visibleCharacters = new List<Character>();
|
private readonly List<Character> visibleCharacters = new List<Character>();
|
||||||
|
|
||||||
private const float UpdateInterval = 0.5f;
|
private const float UpdateInterval = 0.5f;
|
||||||
@@ -48,6 +76,8 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private bool isEquippable;
|
private bool isEquippable;
|
||||||
|
|
||||||
|
private float thermalEffectState;
|
||||||
|
|
||||||
public IEnumerable<Character> VisibleCharacters
|
public IEnumerable<Character> VisibleCharacters
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -81,6 +111,9 @@ namespace Barotrauma.Items.Components
|
|||||||
refEntity = item;
|
refEntity = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
thermalEffectState += deltaTime;
|
||||||
|
thermalEffectState %= 10000.0f;
|
||||||
|
|
||||||
if (updateTimer > 0.0f)
|
if (updateTimer > 0.0f)
|
||||||
{
|
{
|
||||||
updateTimer -= deltaTime;
|
updateTimer -= deltaTime;
|
||||||
@@ -91,6 +124,7 @@ namespace Barotrauma.Items.Components
|
|||||||
foreach (Character c in Character.CharacterList)
|
foreach (Character c in Character.CharacterList)
|
||||||
{
|
{
|
||||||
if (c == equipper || !c.Enabled || c.Removed) { continue; }
|
if (c == equipper || !c.Enabled || c.Removed) { continue; }
|
||||||
|
if (!ShowDeadCharacters && c.IsDead) { continue; }
|
||||||
|
|
||||||
float dist = Vector2.DistanceSquared(refEntity.WorldPosition, c.WorldPosition);
|
float dist = Vector2.DistanceSquared(refEntity.WorldPosition, c.WorldPosition);
|
||||||
if (dist < Range * Range)
|
if (dist < Range * Range)
|
||||||
@@ -123,27 +157,71 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
if (character == null) { return; }
|
if (character == null) { return; }
|
||||||
|
|
||||||
GUI.UIGlow.Draw(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight),
|
if (OverlayColor.A > 0)
|
||||||
Color.LightGreen * 0.5f);
|
|
||||||
|
|
||||||
Character closestCharacter = null;
|
|
||||||
float closestDist = float.PositiveInfinity;
|
|
||||||
foreach (Character c in visibleCharacters)
|
|
||||||
{
|
{
|
||||||
if (c == character || !c.Enabled || c.Removed) { continue; }
|
GUI.UIGlow.Draw(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), OverlayColor);
|
||||||
|
}
|
||||||
|
|
||||||
float dist = Vector2.DistanceSquared(GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition), c.WorldPosition);
|
if (ShowTexts)
|
||||||
if (dist < closestDist)
|
{
|
||||||
|
Character closestCharacter = null;
|
||||||
|
float closestDist = float.PositiveInfinity;
|
||||||
|
foreach (Character c in visibleCharacters)
|
||||||
{
|
{
|
||||||
closestCharacter = c;
|
if (c == character || !c.Enabled || c.Removed) { continue; }
|
||||||
closestDist = dist;
|
|
||||||
|
float dist = Vector2.DistanceSquared(GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition), c.WorldPosition);
|
||||||
|
if (dist < closestDist)
|
||||||
|
{
|
||||||
|
closestCharacter = c;
|
||||||
|
closestDist = dist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closestCharacter != null)
|
||||||
|
{
|
||||||
|
float dist = Vector2.Distance(GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition), closestCharacter.WorldPosition);
|
||||||
|
DrawCharacterInfo(spriteBatch, closestCharacter, 1.0f - MathHelper.Max((dist - (Range - FadeOutRange)) / FadeOutRange, 0.0f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (closestCharacter != null)
|
if (ThermalGoggles)
|
||||||
{
|
{
|
||||||
float dist = Vector2.Distance(GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition), closestCharacter.WorldPosition);
|
spriteBatch.End();
|
||||||
DrawCharacterInfo(spriteBatch, closestCharacter, 1.0f - MathHelper.Max((dist - (Range - FadeOutRange)) / FadeOutRange, 0.0f));
|
GameMain.LightManager.SolidColorEffect.Parameters["color"].SetValue(Color.Red.ToVector4() * (0.3f + MathF.Sin(thermalEffectState) * 0.05f));
|
||||||
|
GameMain.LightManager.SolidColorEffect.CurrentTechnique = GameMain.LightManager.SolidColorEffect.Techniques["SolidColorBlur"];
|
||||||
|
GameMain.LightManager.SolidColorEffect.Parameters["blurDistance"].SetValue(0.01f + MathF.Sin(thermalEffectState) * 0.005f);
|
||||||
|
GameMain.LightManager.SolidColorEffect.CurrentTechnique.Passes[0].Apply();
|
||||||
|
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, transformMatrix: Screen.Selected.Cam.Transform, effect: GameMain.LightManager.SolidColorEffect);
|
||||||
|
|
||||||
|
Entity refEntity = equipper;
|
||||||
|
if (!isEquippable || refEntity == null)
|
||||||
|
{
|
||||||
|
refEntity = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Character c in Character.CharacterList)
|
||||||
|
{
|
||||||
|
if (c == character || !c.Enabled || c.Removed || c.Params.HideInThermalGoggles) { continue; }
|
||||||
|
if (!ShowDeadCharacters && c.IsDead) { continue; }
|
||||||
|
|
||||||
|
float dist = Vector2.DistanceSquared(refEntity.WorldPosition, c.WorldPosition);
|
||||||
|
if (dist > Range * Range) { continue; }
|
||||||
|
|
||||||
|
Sprite pingCircle = GUI.Style.UIThermalGlow.Sprite;
|
||||||
|
foreach (Limb limb in c.AnimController.Limbs)
|
||||||
|
{
|
||||||
|
if (limb.Mass < 1.0f) { continue; }
|
||||||
|
float noise1 = PerlinNoise.GetPerlin((thermalEffectState + limb.Params.ID + c.ID) * 0.01f, (thermalEffectState + limb.Params.ID + c.ID) * 0.02f);
|
||||||
|
float noise2 = PerlinNoise.GetPerlin((thermalEffectState + limb.Params.ID + c.ID) * 0.01f, (thermalEffectState + limb.Params.ID + c.ID) * 0.008f);
|
||||||
|
Vector2 spriteScale = ConvertUnits.ToDisplayUnits(limb.body.GetSize()) / pingCircle.size * (noise1 * 0.5f + 2f);
|
||||||
|
Vector2 drawPos = new Vector2(limb.body.DrawPosition.X + (noise1 - 0.5f) * 100, -limb.body.DrawPosition.Y + (noise2 - 0.5f) * 100);
|
||||||
|
pingCircle.Draw(spriteBatch, drawPos, 0.0f, scale: Math.Max(spriteScale.X, spriteScale.Y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spriteBatch.End();
|
||||||
|
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -177,6 +177,10 @@ namespace Barotrauma.Items.Components
|
|||||||
partial void LaunchProjSpecific()
|
partial void LaunchProjSpecific()
|
||||||
{
|
{
|
||||||
recoilTimer = RetractionTime;
|
recoilTimer = RetractionTime;
|
||||||
|
if (user != null)
|
||||||
|
{
|
||||||
|
recoilTimer /= 1 + user.GetStatValue(StatTypes.TurretAttackSpeed);
|
||||||
|
}
|
||||||
PlaySound(ActionType.OnUse);
|
PlaySound(ActionType.OnUse);
|
||||||
Vector2 particlePos = GetRelativeFiringPosition(UseFiringOffsetForMuzzleFlash);
|
Vector2 particlePos = GetRelativeFiringPosition(UseFiringOffsetForMuzzleFlash);
|
||||||
foreach (ParticleEmitter emitter in particleEmitters)
|
foreach (ParticleEmitter emitter in particleEmitters)
|
||||||
@@ -534,20 +538,20 @@ namespace Barotrauma.Items.Components
|
|||||||
minRotationWidget.Draw(spriteBatch, (float)Timing.Step);
|
minRotationWidget.Draw(spriteBatch, (float)Timing.Step);
|
||||||
maxRotationWidget.Draw(spriteBatch, (float)Timing.Step);
|
maxRotationWidget.Draw(spriteBatch, (float)Timing.Step);
|
||||||
|
|
||||||
Vector2 GetDrawPos()
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
return drawPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateBarrel()
|
void UpdateBarrel()
|
||||||
{
|
{
|
||||||
rotation = (minRotation + maxRotation) / 2;
|
rotation = (minRotation + maxRotation) / 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vector2 GetDrawPos()
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
return drawPos;
|
||||||
|
}
|
||||||
|
|
||||||
private Widget GetWidget(string id, SpriteBatch spriteBatch, int size = 5, float thickness = 1f, Action<Widget> initMethod = null)
|
private Widget GetWidget(string id, SpriteBatch spriteBatch, int size = 5, float thickness = 1f, Action<Widget> initMethod = null)
|
||||||
{
|
{
|
||||||
Vector2 offset = new Vector2(size / 2 + 5, -10);
|
Vector2 offset = new Vector2(size / 2 + 5, -10);
|
||||||
|
|||||||
@@ -5,17 +5,17 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
partial class Wearable
|
partial class Wearable
|
||||||
{
|
{
|
||||||
private void GetDamageModifierText(ref string description, float damageMultiplier, string afflictionIdentifier)
|
private void GetDamageModifierText(ref string description, DamageModifier damageModifier, string afflictionIdentifier)
|
||||||
{
|
{
|
||||||
int roundedValue = (int)Math.Round((1 - damageMultiplier) * 100);
|
int roundedValue = (int)Math.Round((1 - damageModifier.DamageMultiplier * damageModifier.ProbabilityMultiplier) * 100);
|
||||||
if (roundedValue == 0) { return; }
|
if (roundedValue == 0) { return; }
|
||||||
string colorStr = XMLExtensions.ColorToString(GUI.Style.Green);
|
string colorStr = XMLExtensions.ColorToString(GUI.Style.Green);
|
||||||
description += $"\n ‖color:{colorStr}‖{roundedValue.ToString("-0;+#")}%‖color:end‖ {AfflictionPrefab.List.FirstOrDefault(ap => ap.Identifier.Equals(afflictionIdentifier, StringComparison.OrdinalIgnoreCase))?.Name ?? afflictionIdentifier}";
|
description += $"\n ‖color:{colorStr}‖{roundedValue.ToString("-0;+#")}%‖color:end‖ {AfflictionPrefab.List.FirstOrDefault(ap => ap.Identifier.Equals(afflictionIdentifier, StringComparison.OrdinalIgnoreCase))?.Name ?? afflictionIdentifier}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void AddTooltipInfo(ref string description)
|
public override void AddTooltipInfo(ref string name, ref string description)
|
||||||
{
|
{
|
||||||
if (damageModifiers.Any(d => !MathUtils.NearlyEqual(d.DamageMultiplier, 1f)) || SkillModifiers.Any())
|
if (damageModifiers.Any(d => !MathUtils.NearlyEqual(d.DamageMultiplier, 1f) || !MathUtils.NearlyEqual(d.ProbabilityMultiplier, 1f)) || SkillModifiers.Any())
|
||||||
{
|
{
|
||||||
description += "\n";
|
description += "\n";
|
||||||
}
|
}
|
||||||
@@ -31,11 +31,11 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
foreach (string afflictionIdentifier in damageModifier.ParsedAfflictionIdentifiers)
|
foreach (string afflictionIdentifier in damageModifier.ParsedAfflictionIdentifiers)
|
||||||
{
|
{
|
||||||
GetDamageModifierText(ref description, damageModifier.DamageMultiplier, afflictionIdentifier);
|
GetDamageModifierText(ref description, damageModifier, afflictionIdentifier);
|
||||||
}
|
}
|
||||||
foreach (string afflictionIdentifier in damageModifier.ParsedAfflictionTypes)
|
foreach (string afflictionIdentifier in damageModifier.ParsedAfflictionTypes)
|
||||||
{
|
{
|
||||||
GetDamageModifierText(ref description, damageModifier.DamageMultiplier, afflictionIdentifier);
|
GetDamageModifierText(ref description, damageModifier, afflictionIdentifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -297,9 +297,10 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string name = item.Name;
|
||||||
foreach (ItemComponent component in item.Components)
|
foreach (ItemComponent component in item.Components)
|
||||||
{
|
{
|
||||||
component.AddTooltipInfo(ref description);
|
component.AddTooltipInfo(ref name, ref description);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.Prefab.ShowContentsInTooltip && item.OwnInventory != null)
|
if (item.Prefab.ShowContentsInTooltip && item.OwnInventory != null)
|
||||||
@@ -315,12 +316,18 @@ namespace Barotrauma
|
|||||||
|
|
||||||
string colorStr = XMLExtensions.ColorToString(!item.AllowStealing ? GUI.Style.Red : Color.White);
|
string colorStr = XMLExtensions.ColorToString(!item.AllowStealing ? GUI.Style.Red : Color.White);
|
||||||
|
|
||||||
toolTip = $"‖color:{colorStr}‖{item.Name}‖color:end‖";
|
toolTip = $"‖color:{colorStr}‖{name}‖color:end‖";
|
||||||
|
if (item.GetComponent<Quality>() != null)
|
||||||
|
{
|
||||||
|
// substring by to get rid of the empty space at start, text file should be adjusted
|
||||||
|
toolTip += $"\n{TextManager.GetWithVariable("itemname.quality" + item.Quality, "[itemname]", "", fallBackTag: "itemname.quality3")?.Substring(1)}";
|
||||||
|
}
|
||||||
|
|
||||||
if (itemsInSlot.All(it => it.NonInteractable || it.NonPlayerTeamInteractable))
|
if (itemsInSlot.All(it => it.NonInteractable || it.NonPlayerTeamInteractable))
|
||||||
{
|
{
|
||||||
toolTip += " " + TextManager.Get("connectionlocked");
|
toolTip += " " + TextManager.Get("connectionlocked");
|
||||||
}
|
}
|
||||||
if (!item.IsFullCondition && !item.Prefab.HideConditionBar)
|
if (!item.IsFullCondition && !item.Prefab.HideConditionInTooltip)
|
||||||
{
|
{
|
||||||
string conditionColorStr = XMLExtensions.ColorToString(ToolBox.GradientLerp(item.Condition / item.MaxCondition, GUI.Style.ColorInventoryEmpty, GUI.Style.ColorInventoryHalf, GUI.Style.ColorInventoryFull));
|
string conditionColorStr = XMLExtensions.ColorToString(ToolBox.GradientLerp(item.Condition / item.MaxCondition, GUI.Style.ColorInventoryEmpty, GUI.Style.ColorInventoryHalf, GUI.Style.ColorInventoryFull));
|
||||||
toolTip += $"‖color:{conditionColorStr}‖ ({(int)item.ConditionPercentage} %)‖color:end‖";
|
toolTip += $"‖color:{conditionColorStr}‖ ({(int)item.ConditionPercentage} %)‖color:end‖";
|
||||||
@@ -478,7 +485,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (container == null) { return false; }
|
if (container == null) { return false; }
|
||||||
return owner.SelectedCharacter != null|| (!(owner is Character character)) || !container.KeepOpenWhenEquippedBy(character) || !owner.HasEquippedItem(container.Item);
|
return owner.SelectedCharacter != null|| (!(owner is Character character)) || !container.KeepOpenWhenEquippedBy(character) || !owner.HasEquippedItem(container.Item);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual bool HideSlot(int i)
|
protected virtual bool HideSlot(int i)
|
||||||
@@ -594,7 +601,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
var slotRef = new SlotReference(this, slot, slotIndex, isSubSlot, slots[slotIndex].FirstOrDefault()?.GetComponent<ItemContainer>()?.Inventory);
|
var slotRef = new SlotReference(this, slot, slotIndex, isSubSlot, slots[slotIndex].FirstOrDefault()?.GetComponent<ItemContainer>()?.Inventory);
|
||||||
if (Screen.Selected is SubEditorScreen editor && !editor.WiringMode && slotRef.ParentInventory is CharacterInventory) { return; }
|
if (Screen.Selected is SubEditorScreen editor && !editor.WiringMode && slotRef.ParentInventory is CharacterInventory) { return; }
|
||||||
selectedSlot = slotRef;
|
if (CanSelectSlot(slotRef))
|
||||||
|
{
|
||||||
|
selectedSlot = slotRef;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!DraggingItems.Any())
|
if (!DraggingItems.Any())
|
||||||
@@ -667,6 +677,10 @@ namespace Barotrauma
|
|||||||
if (subInventory.visualSlots == null) { subInventory.CreateSlots(); }
|
if (subInventory.visualSlots == null) { subInventory.CreateSlots(); }
|
||||||
|
|
||||||
canMove = container.MovableFrame && !subInventory.IsInventoryHoverAvailable(Owner as Character, container) && subInventory.originalPos != Point.Zero;
|
canMove = container.MovableFrame && !subInventory.IsInventoryHoverAvailable(Owner as Character, container) && subInventory.originalPos != Point.Zero;
|
||||||
|
if (this is CharacterInventory characterInventory && characterInventory.CurrentLayout != CharacterInventory.Layout.Default)
|
||||||
|
{
|
||||||
|
canMove = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (canMove)
|
if (canMove)
|
||||||
{
|
{
|
||||||
@@ -715,7 +729,7 @@ namespace Barotrauma
|
|||||||
spacing = new Vector2(10 * UIScale, (10 + UnequippedIndicator.size.Y) * UIScale);
|
spacing = new Vector2(10 * UIScale, (10 + UnequippedIndicator.size.Y) * UIScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
int columns = (int)Math.Max(Math.Floor(Math.Sqrt(itemCapacity)), 1);
|
int columns = MathHelper.Clamp((int)Math.Floor(Math.Sqrt(itemCapacity)), 1, container.SlotsPerRow);
|
||||||
while (itemCapacity / columns * (subRect.Height + spacing.Y) > GameMain.GraphicsHeight * 0.5f)
|
while (itemCapacity / columns * (subRect.Height + spacing.Y) > GameMain.GraphicsHeight * 0.5f)
|
||||||
{
|
{
|
||||||
columns++;
|
columns++;
|
||||||
@@ -826,11 +840,23 @@ namespace Barotrauma
|
|||||||
return rect.Contains(PlayerInput.MousePosition);
|
return rect.Contains(PlayerInput.MousePosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool IsMouseOnInventory
|
||||||
|
{
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Refresh the value of IsMouseOnInventory
|
||||||
|
/// </summary>
|
||||||
|
public static void RefreshMouseOnInventory()
|
||||||
|
{
|
||||||
|
IsMouseOnInventory = DetermineMouseOnInventory();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Is the mouse on any inventory element (slot, equip button, subinventory...)
|
/// Is the mouse on any inventory element (slot, equip button, subinventory...)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
private static bool DetermineMouseOnInventory(bool ignoreDraggedItem = false)
|
||||||
public static bool IsMouseOnInventory(bool ignoreDraggedItem = false)
|
|
||||||
{
|
{
|
||||||
if (GameMain.GameSession?.Campaign != null &&
|
if (GameMain.GameSession?.Campaign != null &&
|
||||||
(GameMain.GameSession.Campaign.ShowCampaignUI || GameMain.GameSession.Campaign.ForceMapUI))
|
(GameMain.GameSession.Campaign.ShowCampaignUI || GameMain.GameSession.Campaign.ForceMapUI))
|
||||||
@@ -1112,7 +1138,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Character.Controlled.ClearInputs();
|
Character.Controlled.ClearInputs();
|
||||||
|
|
||||||
if (!IsMouseOnInventory(ignoreDraggedItem: true) &&
|
if (!DetermineMouseOnInventory(ignoreDraggedItem: true) &&
|
||||||
CharacterHealth.OpenHealthWindow != null)
|
CharacterHealth.OpenHealthWindow != null)
|
||||||
{
|
{
|
||||||
bool dropSuccessful = false;
|
bool dropSuccessful = false;
|
||||||
@@ -1279,34 +1305,52 @@ namespace Barotrauma
|
|||||||
DraggingItems.Clear();
|
DraggingItems.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedSlot != null)
|
if (selectedSlot != null && !CanSelectSlot(selectedSlot))
|
||||||
{
|
{
|
||||||
if (!selectedSlot.Slot.MouseOn())
|
selectedSlot = null;
|
||||||
{
|
|
||||||
selectedSlot = null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var rootOwner = (selectedSlot.ParentInventory?.Owner as Item)?.GetRootInventoryOwner();
|
|
||||||
if (selectedSlot.ParentInventory?.Owner != Character.Controlled &&
|
|
||||||
selectedSlot.ParentInventory?.Owner != Character.Controlled.SelectedCharacter &&
|
|
||||||
selectedSlot.ParentInventory?.Owner != Character.Controlled.SelectedConstruction &&
|
|
||||||
!(Character.Controlled.SelectedConstruction?.linkedTo.Contains(selectedSlot.ParentInventory?.Owner) ?? false) &&
|
|
||||||
rootOwner != Character.Controlled &&
|
|
||||||
rootOwner != Character.Controlled.SelectedCharacter &&
|
|
||||||
rootOwner != Character.Controlled.SelectedConstruction &&
|
|
||||||
!(Character.Controlled.SelectedConstruction?.linkedTo.Contains(rootOwner) ?? false))
|
|
||||||
{
|
|
||||||
selectedSlot = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool CanSelectSlot(SlotReference selectedSlot)
|
||||||
|
{
|
||||||
|
if (!selectedSlot.Slot.MouseOn())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var rootOwner = (selectedSlot.ParentInventory?.Owner as Item)?.GetRootInventoryOwner();
|
||||||
|
if (selectedSlot.ParentInventory?.Owner != Character.Controlled &&
|
||||||
|
selectedSlot.ParentInventory?.Owner != Character.Controlled.SelectedCharacter &&
|
||||||
|
selectedSlot.ParentInventory?.Owner != Character.Controlled.SelectedConstruction &&
|
||||||
|
!(Character.Controlled.SelectedConstruction?.linkedTo.Contains(selectedSlot.ParentInventory?.Owner) ?? false) &&
|
||||||
|
rootOwner != Character.Controlled &&
|
||||||
|
rootOwner != Character.Controlled.SelectedCharacter &&
|
||||||
|
rootOwner != Character.Controlled.SelectedConstruction &&
|
||||||
|
!(Character.Controlled.SelectedConstruction?.linkedTo.Contains(rootOwner) ?? false))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var parentItem = (selectedSlot?.ParentInventory?.Owner as Item) ?? selectedSlot?.Item;
|
||||||
|
if ((parentItem?.GetRootInventoryOwner() is Character ownerCharacter) &&
|
||||||
|
ownerCharacter == Character.Controlled &&
|
||||||
|
CharacterHealth.OpenHealthWindow?.Character != ownerCharacter &&
|
||||||
|
ownerCharacter.Inventory.IsInLimbSlot(parentItem, InvSlotType.HealthInterface))
|
||||||
|
{
|
||||||
|
highlightedSubInventorySlots.RemoveWhere(s => s.Item == parentItem);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected static Rectangle GetSubInventoryHoverArea(SlotReference subSlot)
|
protected static Rectangle GetSubInventoryHoverArea(SlotReference subSlot)
|
||||||
{
|
{
|
||||||
Rectangle hoverArea;
|
Rectangle hoverArea;
|
||||||
if (!subSlot.Inventory.Movable() || Character.Controlled?.Inventory == subSlot.ParentInventory && !Character.Controlled.HasEquippedItem(subSlot.Item))
|
if (!subSlot.Inventory.Movable() ||
|
||||||
|
(Character.Controlled?.Inventory == subSlot.ParentInventory && !Character.Controlled.HasEquippedItem(subSlot.Item)) ||
|
||||||
|
(subSlot.ParentInventory is CharacterInventory characterInventory && characterInventory.CurrentLayout != CharacterInventory.Layout.Default))
|
||||||
{
|
{
|
||||||
hoverArea = subSlot.Slot.Rect;
|
hoverArea = subSlot.Slot.Rect;
|
||||||
hoverArea.Location += subSlot.Slot.DrawOffset.ToPoint();
|
hoverArea.Location += subSlot.Slot.DrawOffset.ToPoint();
|
||||||
@@ -1375,7 +1419,7 @@ namespace Barotrauma
|
|||||||
float scale = Math.Min(Math.Min(iconSize / sprite.size.X, iconSize / sprite.size.Y), 1.5f);
|
float scale = Math.Min(Math.Min(iconSize / sprite.size.X, iconSize / sprite.size.Y), 1.5f);
|
||||||
Vector2 itemPos = PlayerInput.MousePosition;
|
Vector2 itemPos = PlayerInput.MousePosition;
|
||||||
|
|
||||||
bool mouseOnHealthInterface = CharacterHealth.OpenHealthWindow != null && CharacterHealth.OpenHealthWindow.MouseOnElement;
|
bool mouseOnHealthInterface = CharacterHealth.OpenHealthWindow != null && CharacterHealth.OpenHealthWindow.MouseOnElement && DraggingItems.Any(it => it.UseInHealthInterface);
|
||||||
|
|
||||||
if ((GUI.MouseOn == null || mouseOnHealthInterface) && selectedSlot == null)
|
if ((GUI.MouseOn == null || mouseOnHealthInterface) && selectedSlot == null)
|
||||||
{
|
{
|
||||||
@@ -1434,7 +1478,8 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
Color slotColor = Color.White;
|
Color slotColor = Color.White;
|
||||||
if (inventory?.Owner is Item i && !i.IsPlayerTeamInteractable) { slotColor = Color.Gray; }
|
Item parentItem = inventory?.Owner as Item;
|
||||||
|
if (parentItem != null && !parentItem.IsPlayerTeamInteractable) { slotColor = Color.Gray; }
|
||||||
var itemContainer = item?.GetComponent<ItemContainer>();
|
var itemContainer = item?.GetComponent<ItemContainer>();
|
||||||
if (itemContainer != null && (itemContainer.InventoryTopSprite != null || itemContainer.InventoryBottomSprite != null))
|
if (itemContainer != null && (itemContainer.InventoryTopSprite != null || itemContainer.InventoryBottomSprite != null))
|
||||||
{
|
{
|
||||||
@@ -1513,7 +1558,7 @@ namespace Barotrauma
|
|||||||
var indicatorStyle = GUI.Style.GetComponentStyle("ContainedStateIndicator.Default");
|
var indicatorStyle = GUI.Style.GetComponentStyle("ContainedStateIndicator.Default");
|
||||||
Sprite indicatorSprite = indicatorStyle?.GetDefaultSprite();
|
Sprite indicatorSprite = indicatorStyle?.GetDefaultSprite();
|
||||||
Sprite emptyIndicatorSprite = indicatorStyle?.GetSprite(GUIComponent.ComponentState.Hover);
|
Sprite emptyIndicatorSprite = indicatorStyle?.GetSprite(GUIComponent.ComponentState.Hover);
|
||||||
DrawItemStateIndicator(spriteBatch, inventory, indicatorSprite, emptyIndicatorSprite, conditionIndicatorArea, item.Condition / item.MaxCondition);
|
DrawItemStateIndicator(spriteBatch, inventory, indicatorSprite, emptyIndicatorSprite, conditionIndicatorArea, item.Condition / item.MaxCondition);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemContainer != null && itemContainer.ShowContainedStateIndicator)
|
if (itemContainer != null && itemContainer.ShowContainedStateIndicator)
|
||||||
@@ -1525,14 +1570,14 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var containedItem = itemContainer.Inventory.slots[0].FirstOrDefault();
|
var containedItem = itemContainer.Inventory.slots[Math.Max(itemContainer.ContainedStateIndicatorSlot, 0)].FirstOrDefault();
|
||||||
containedState = itemContainer.Inventory.Capacity == 1 ?
|
containedState = itemContainer.Inventory.Capacity == 1 || itemContainer.ContainedStateIndicatorSlot > -1 ?
|
||||||
(containedItem == null ? 0.0f : containedItem.Condition / containedItem.MaxCondition) :
|
(containedItem == null ? 0.0f : containedItem.Condition / containedItem.MaxCondition) :
|
||||||
itemContainer.Inventory.slots.Count(i => !i.Empty()) / (float)itemContainer.Inventory.capacity;
|
itemContainer.Inventory.slots.Count(i => !i.Empty()) / (float)itemContainer.Inventory.capacity;
|
||||||
if (containedItem != null && itemContainer.Inventory.Capacity == 1)
|
if (containedItem != null && itemContainer.Inventory.Capacity == 1)
|
||||||
{
|
{
|
||||||
int maxStackSize = Math.Min(containedItem.Prefab.MaxStackSize, itemContainer.MaxStackSize);
|
int maxStackSize = Math.Min(containedItem.Prefab.MaxStackSize, itemContainer.GetMaxStackSize(0));
|
||||||
if (maxStackSize > 1)
|
if (maxStackSize > 1 || containedItem.Prefab.HideConditionBar)
|
||||||
{
|
{
|
||||||
containedState = itemContainer.Inventory.slots[0].ItemCount / (float)maxStackSize;
|
containedState = itemContainer.Inventory.slots[0].ItemCount / (float)maxStackSize;
|
||||||
}
|
}
|
||||||
@@ -1556,6 +1601,27 @@ namespace Barotrauma
|
|||||||
DrawItemStateIndicator(spriteBatch, inventory, indicatorSprite, emptyIndicatorSprite, containedIndicatorArea, containedState,
|
DrawItemStateIndicator(spriteBatch, inventory, indicatorSprite, emptyIndicatorSprite, containedIndicatorArea, containedState,
|
||||||
pulsate: !usingDefaultSprite && containedState >= 0.0f && containedState < 0.25f && inventory == Character.Controlled?.Inventory && Character.Controlled.HasEquippedItem(item));
|
pulsate: !usingDefaultSprite && containedState >= 0.0f && containedState < 0.25f && inventory == Character.Controlled?.Inventory && Character.Controlled.HasEquippedItem(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (item.Quality != 0)
|
||||||
|
{
|
||||||
|
var style = GUI.Style.GetComponentStyle("InnerGlowSmall");
|
||||||
|
if (style == null)
|
||||||
|
{
|
||||||
|
GUI.DrawRectangle(spriteBatch, rect, GUI.Style.GetQualityColor(item.Quality) * 0.7f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
style.Sprites[GUIComponent.ComponentState.None].FirstOrDefault()?.Draw(spriteBatch, rect, GUI.Style.GetQualityColor(item.Quality) * 0.5f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var slotIcon = parentItem?.GetComponent<ItemContainer>()?.GetSlotIcon(slotIndex);
|
||||||
|
if (slotIcon != null)
|
||||||
|
{
|
||||||
|
slotIcon.Draw(spriteBatch, rect.Center.ToVector2(), GUI.Style.EquipmentSlotIconColor, scale: Math.Min(rect.Width / slotIcon.size.X, rect.Height / slotIcon.size.Y) * 0.8f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1590,7 +1656,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
Color spriteColor = sprite == item.Sprite ? item.GetSpriteColor() : item.GetInventoryIconColor();
|
Color spriteColor = sprite == item.Sprite ? item.GetSpriteColor() : item.GetInventoryIconColor();
|
||||||
if (inventory != null && (inventory.Locked || inventory.slots[slotIndex].Items.All(it => it.NonInteractable || it.NonPlayerTeamInteractable))) { spriteColor *= 0.5f; }
|
if (inventory != null && (inventory.Locked || inventory.slots[slotIndex].Items.All(it => it.NonInteractable || it.NonPlayerTeamInteractable))) { spriteColor *= 0.5f; }
|
||||||
if (CharacterHealth.OpenHealthWindow != null && !item.UseInHealthInterface)
|
if (CharacterHealth.OpenHealthWindow != null && !item.UseInHealthInterface && !item.AllowedSlots.Contains(InvSlotType.HealthInterface) && item.GetComponent<GeneticMaterial>() == null)
|
||||||
{
|
{
|
||||||
spriteColor = Color.Lerp(spriteColor, Color.TransparentBlack, 0.5f);
|
spriteColor = Color.Lerp(spriteColor, Color.TransparentBlack, 0.5f);
|
||||||
}
|
}
|
||||||
@@ -1611,9 +1677,9 @@ namespace Barotrauma
|
|||||||
scale: iconSize.X / stealIcon.size.X);
|
scale: iconSize.X / stealIcon.size.X);
|
||||||
}
|
}
|
||||||
int maxStackSize = item.Prefab.MaxStackSize;
|
int maxStackSize = item.Prefab.MaxStackSize;
|
||||||
if (item.Container != null)
|
if (inventory is ItemInventory itemInventory)
|
||||||
{
|
{
|
||||||
maxStackSize = Math.Min(maxStackSize, item.Container.GetComponent<ItemContainer>()?.MaxStackSize ?? maxStackSize);
|
maxStackSize = Math.Min(maxStackSize, itemInventory.Container.GetMaxStackSize(slotIndex));
|
||||||
}
|
}
|
||||||
if (maxStackSize > 1 && inventory != null)
|
if (maxStackSize > 1 && inventory != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
BrokenItemSprite fadeInBrokenSprite = null;
|
BrokenItemSprite fadeInBrokenSprite = null;
|
||||||
float fadeInBrokenSpriteAlpha = 0.0f;
|
float fadeInBrokenSpriteAlpha = 0.0f;
|
||||||
float displayCondition = FakeBroken ? 0.0f : condition;
|
float displayCondition = FakeBroken ? 0.0f : ConditionPercentage;
|
||||||
Vector2 drawOffset = Vector2.Zero;
|
Vector2 drawOffset = Vector2.Zero;
|
||||||
if (displayCondition < MaxCondition)
|
if (displayCondition < MaxCondition)
|
||||||
{
|
{
|
||||||
@@ -326,13 +326,18 @@ namespace Barotrauma
|
|||||||
size, color: color,
|
size, color: color,
|
||||||
textureScale: Vector2.One * Scale,
|
textureScale: Vector2.One * Scale,
|
||||||
depth: depth);
|
depth: depth);
|
||||||
fadeInBrokenSprite?.Sprite.DrawTiled(spriteBatch, new Vector2(DrawPosition.X - rect.Width / 2, -(DrawPosition.Y + rect.Height / 2)) + fadeInBrokenSprite.Offset.ToVector2() * Scale, size, color: color * fadeInBrokenSpriteAlpha,
|
|
||||||
textureScale: Vector2.One * Scale,
|
if (fadeInBrokenSprite != null)
|
||||||
depth: depth - 0.000001f);
|
{
|
||||||
|
float d = Math.Min(depth + (fadeInBrokenSprite.Sprite.Depth - activeSprite.Depth - 0.000001f), 0.999f);
|
||||||
|
fadeInBrokenSprite.Sprite.DrawTiled(spriteBatch, new Vector2(DrawPosition.X - rect.Width / 2, -(DrawPosition.Y + rect.Height / 2)) + fadeInBrokenSprite.Offset.ToVector2() * Scale, size, color: color * fadeInBrokenSpriteAlpha,
|
||||||
|
textureScale: Vector2.One * Scale,
|
||||||
|
depth: d);
|
||||||
|
}
|
||||||
foreach (var decorativeSprite in Prefab.DecorativeSprites)
|
foreach (var decorativeSprite in Prefab.DecorativeSprites)
|
||||||
{
|
{
|
||||||
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
||||||
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, spriteAnimState[decorativeSprite].RandomOffsetMultiplier, -rotationRad) * Scale;
|
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, spriteAnimState[decorativeSprite].RandomOffsetMultiplier, flippedX && Prefab.CanSpriteFlipX ? rotationRad : -rotationRad) * Scale;
|
||||||
if (flippedX && Prefab.CanSpriteFlipX) { offset.X = -offset.X; }
|
if (flippedX && Prefab.CanSpriteFlipX) { offset.X = -offset.X; }
|
||||||
if (flippedY && Prefab.CanSpriteFlipY) { offset.Y = -offset.Y; }
|
if (flippedY && Prefab.CanSpriteFlipY) { offset.Y = -offset.Y; }
|
||||||
decorativeSprite.Sprite.DrawTiled(spriteBatch,
|
decorativeSprite.Sprite.DrawTiled(spriteBatch,
|
||||||
@@ -357,7 +362,11 @@ namespace Barotrauma
|
|||||||
if (color.A > 0)
|
if (color.A > 0)
|
||||||
{
|
{
|
||||||
activeSprite.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y) + drawOffset, color, origin, rotationRad, Scale, activeSprite.effects, depth);
|
activeSprite.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y) + drawOffset, color, origin, rotationRad, Scale, activeSprite.effects, depth);
|
||||||
fadeInBrokenSprite?.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y) + fadeInBrokenSprite.Offset.ToVector2() * Scale, color * fadeInBrokenSpriteAlpha, origin, rotationRad, Scale, activeSprite.effects, depth - 0.000001f);
|
if (fadeInBrokenSprite != null)
|
||||||
|
{
|
||||||
|
float d = Math.Min(depth + (fadeInBrokenSprite.Sprite.Depth - activeSprite.Depth - 0.000001f), 0.999f);
|
||||||
|
fadeInBrokenSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y) + fadeInBrokenSprite.Offset.ToVector2() * Scale, color * fadeInBrokenSpriteAlpha, origin, rotationRad, Scale, activeSprite.effects, d);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (Infector != null && (Infector.ParentBallastFlora.HasBrokenThrough || BallastFloraBehavior.AlwaysShowBallastFloraSprite))
|
if (Infector != null && (Infector.ParentBallastFlora.HasBrokenThrough || BallastFloraBehavior.AlwaysShowBallastFloraSprite))
|
||||||
{
|
{
|
||||||
@@ -368,7 +377,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
||||||
float rot = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState, spriteAnimState[decorativeSprite].RandomRotationFactor);
|
float rot = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState, spriteAnimState[decorativeSprite].RandomRotationFactor);
|
||||||
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, spriteAnimState[decorativeSprite].RandomOffsetMultiplier, -rotationRad) * Scale;
|
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, spriteAnimState[decorativeSprite].RandomOffsetMultiplier, flippedX && Prefab.CanSpriteFlipX ? rotationRad : -rotationRad) * Scale;
|
||||||
if (flippedX && Prefab.CanSpriteFlipX) { offset.X = -offset.X; }
|
if (flippedX && Prefab.CanSpriteFlipX) { offset.X = -offset.X; }
|
||||||
if (flippedY && Prefab.CanSpriteFlipY) { offset.Y = -offset.Y; }
|
if (flippedY && Prefab.CanSpriteFlipY) { offset.Y = -offset.Y; }
|
||||||
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + offset.X, -(DrawPosition.Y + offset.Y)), color,
|
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + offset.X, -(DrawPosition.Y + offset.Y)), color,
|
||||||
@@ -410,8 +419,11 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
body.Draw(spriteBatch, activeSprite, color, depth, Scale);
|
body.Draw(spriteBatch, activeSprite, color, depth, Scale);
|
||||||
if (fadeInBrokenSprite != null) { body.Draw(spriteBatch, fadeInBrokenSprite.Sprite, color * fadeInBrokenSpriteAlpha, depth - 0.000001f, Scale); }
|
if (fadeInBrokenSprite != null)
|
||||||
|
{
|
||||||
|
float d = Math.Min(depth + (fadeInBrokenSprite.Sprite.Depth - activeSprite.Depth - 0.000001f), 0.999f);
|
||||||
|
body.Draw(spriteBatch, fadeInBrokenSprite.Sprite, color * fadeInBrokenSpriteAlpha, d, Scale);
|
||||||
|
}
|
||||||
foreach (var decorativeSprite in Prefab.DecorativeSprites)
|
foreach (var decorativeSprite in Prefab.DecorativeSprites)
|
||||||
{
|
{
|
||||||
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
||||||
@@ -464,6 +476,11 @@ namespace Barotrauma
|
|||||||
if (GameMain.DebugDraw)
|
if (GameMain.DebugDraw)
|
||||||
{
|
{
|
||||||
body?.DebugDraw(spriteBatch, Color.White);
|
body?.DebugDraw(spriteBatch, Color.White);
|
||||||
|
if (GetComponent<TriggerComponent>()?.PhysicsBody is PhysicsBody triggerBody)
|
||||||
|
{
|
||||||
|
triggerBody.UpdateDrawPosition();
|
||||||
|
triggerBody.DebugDraw(spriteBatch, Color.White);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (editing && IsSelected && PlayerInput.KeyDown(Keys.Space))
|
if (editing && IsSelected && PlayerInput.KeyDown(Keys.Space))
|
||||||
@@ -704,6 +721,7 @@ namespace Barotrauma
|
|||||||
new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityX"), style: "GUIButtonSmall")
|
new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityX"), style: "GUIButtonSmall")
|
||||||
{
|
{
|
||||||
ToolTip = TextManager.Get("MirrorEntityXToolTip"),
|
ToolTip = TextManager.Get("MirrorEntityXToolTip"),
|
||||||
|
Enabled = Prefab.CanFlipX,
|
||||||
OnClicked = (button, data) =>
|
OnClicked = (button, data) =>
|
||||||
{
|
{
|
||||||
foreach (MapEntity me in SelectedList)
|
foreach (MapEntity me in SelectedList)
|
||||||
@@ -717,6 +735,7 @@ namespace Barotrauma
|
|||||||
new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityY"), style: "GUIButtonSmall")
|
new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityY"), style: "GUIButtonSmall")
|
||||||
{
|
{
|
||||||
ToolTip = TextManager.Get("MirrorEntityYToolTip"),
|
ToolTip = TextManager.Get("MirrorEntityYToolTip"),
|
||||||
|
Enabled = Prefab.CanFlipY,
|
||||||
OnClicked = (button, data) =>
|
OnClicked = (button, data) =>
|
||||||
{
|
{
|
||||||
foreach (MapEntity me in SelectedList)
|
foreach (MapEntity me in SelectedList)
|
||||||
@@ -1068,7 +1087,7 @@ namespace Barotrauma
|
|||||||
foreach (Character otherCharacter in Character.CharacterList)
|
foreach (Character otherCharacter in Character.CharacterList)
|
||||||
{
|
{
|
||||||
if (otherCharacter != character &&
|
if (otherCharacter != character &&
|
||||||
otherCharacter.SelectedConstruction == character.SelectedConstruction)
|
otherCharacter.SelectedConstruction == this)
|
||||||
{
|
{
|
||||||
ItemInUseWarning.Visible = true;
|
ItemInUseWarning.Visible = true;
|
||||||
if (mergedHUDRect.Width > GameMain.GraphicsWidth / 2) { mergedHUDRect.Inflate(-GameMain.GraphicsWidth / 4, 0); }
|
if (mergedHUDRect.Width > GameMain.GraphicsWidth / 2) { mergedHUDRect.Inflate(-GameMain.GraphicsWidth / 4, 0); }
|
||||||
@@ -1180,7 +1199,7 @@ namespace Barotrauma
|
|||||||
return texts;
|
return texts;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void AddToGUIUpdateList()
|
public override void AddToGUIUpdateList(int order = 0)
|
||||||
{
|
{
|
||||||
if (Screen.Selected is SubEditorScreen)
|
if (Screen.Selected is SubEditorScreen)
|
||||||
{
|
{
|
||||||
@@ -1194,7 +1213,14 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Character.Controlled != null && Character.Controlled.SelectedConstruction != this) { return; }
|
if (Character.Controlled != null && Character.Controlled.SelectedConstruction != this && GetComponent<RemoteController>() == null)
|
||||||
|
{
|
||||||
|
if (Character.Controlled.SelectedConstruction?.GetComponent<RemoteController>()?.TargetItem != this &&
|
||||||
|
!Character.Controlled.HeldItems.Any(it => it.GetComponent<RemoteController>()?.TargetItem == this))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool needsLayoutUpdate = false;
|
bool needsLayoutUpdate = false;
|
||||||
foreach (ItemComponent ic in activeHUDs)
|
foreach (ItemComponent ic in activeHUDs)
|
||||||
@@ -1205,7 +1231,7 @@ namespace Barotrauma
|
|||||||
bool wasUsingAlternativeLayout = ic.UseAlternativeLayout;
|
bool wasUsingAlternativeLayout = ic.UseAlternativeLayout;
|
||||||
ic.UseAlternativeLayout = useAlternativeLayout;
|
ic.UseAlternativeLayout = useAlternativeLayout;
|
||||||
needsLayoutUpdate |= ic.UseAlternativeLayout != wasUsingAlternativeLayout;
|
needsLayoutUpdate |= ic.UseAlternativeLayout != wasUsingAlternativeLayout;
|
||||||
ic.AddToGUIUpdateList();
|
ic.AddToGUIUpdateList(order);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemInUseWarning != null && itemInUseWarning.Visible)
|
if (itemInUseWarning != null && itemInUseWarning.Visible)
|
||||||
@@ -1530,6 +1556,7 @@ namespace Barotrauma
|
|||||||
byte bodyType = msg.ReadByte();
|
byte bodyType = msg.ReadByte();
|
||||||
bool spawnedInOutpost = msg.ReadBoolean();
|
bool spawnedInOutpost = msg.ReadBoolean();
|
||||||
bool allowStealing = msg.ReadBoolean();
|
bool allowStealing = msg.ReadBoolean();
|
||||||
|
int quality = msg.ReadRangedInteger(0, Items.Components.Quality.MaxQuality);
|
||||||
byte teamID = msg.ReadByte();
|
byte teamID = msg.ReadByte();
|
||||||
bool tagsChanged = msg.ReadBoolean();
|
bool tagsChanged = msg.ReadBoolean();
|
||||||
string tags = "";
|
string tags = "";
|
||||||
@@ -1605,7 +1632,8 @@ namespace Barotrauma
|
|||||||
item = new Item(itemPrefab, pos, sub, id: itemId)
|
item = new Item(itemPrefab, pos, sub, id: itemId)
|
||||||
{
|
{
|
||||||
SpawnedInOutpost = spawnedInOutpost,
|
SpawnedInOutpost = spawnedInOutpost,
|
||||||
AllowStealing = allowStealing
|
AllowStealing = allowStealing,
|
||||||
|
Quality = quality
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -1623,6 +1651,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
wifiComponent.TeamID = (CharacterTeamType)teamID;
|
wifiComponent.TeamID = (CharacterTeamType)teamID;
|
||||||
}
|
}
|
||||||
|
foreach (IdCard idCard in item.GetComponents<IdCard>())
|
||||||
|
{
|
||||||
|
idCard.TeamID = (CharacterTeamType)teamID;
|
||||||
|
}
|
||||||
if (descriptionChanged) { item.Description = itemDesc; }
|
if (descriptionChanged) { item.Description = itemDesc; }
|
||||||
if (tagsChanged) { item.Tags = tags; }
|
if (tagsChanged) { item.Tags = tags; }
|
||||||
var nameTag = item.GetComponent<NameTag>();
|
var nameTag = item.GetComponent<NameTag>();
|
||||||
|
|||||||
@@ -77,6 +77,13 @@ namespace Barotrauma
|
|||||||
protected set;
|
protected set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Serialize(true, false)]
|
||||||
|
public bool ShowInStatusMonitor
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
[Serialize("", false)]
|
[Serialize("", false)]
|
||||||
public string ImpactSoundTag { get; private set; }
|
public string ImpactSoundTag { get; private set; }
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
partial void ExplodeProjSpecific(Vector2 worldPosition, Hull hull)
|
partial void ExplodeProjSpecific(Vector2 worldPosition, Hull hull)
|
||||||
{
|
{
|
||||||
|
if (GameMain.Client?.MidRoundSyncing ?? false) { return; }
|
||||||
|
|
||||||
if (shockwave)
|
if (shockwave)
|
||||||
{
|
{
|
||||||
GameMain.ParticleManager.CreateParticle("shockwave", worldPosition,
|
GameMain.ParticleManager.CreateParticle("shockwave", worldPosition,
|
||||||
|
|||||||
@@ -676,7 +676,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
remoteBackgroundSections.Add(new BackgroundSection(new Rectangle(0, 0, 1, 1), i, colorStrength, color, 0));
|
remoteBackgroundSections.Add(new BackgroundSection(new Rectangle(0, 0, 1, 1), (ushort)i, colorStrength, color, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
paintAmount = BackgroundSections.Sum(s => s.ColorStrength);
|
paintAmount = BackgroundSections.Sum(s => s.ColorStrength);
|
||||||
|
|||||||
@@ -7,14 +7,9 @@ namespace Barotrauma.RuinGeneration
|
|||||||
{
|
{
|
||||||
public void DebugDraw(SpriteBatch spriteBatch)
|
public void DebugDraw(SpriteBatch spriteBatch)
|
||||||
{
|
{
|
||||||
foreach (RuinShape shape in allShapes)
|
Rectangle drawRect = Area;
|
||||||
{
|
drawRect.Y = -drawRect.Y - Area.Height;
|
||||||
GUI.DrawString(spriteBatch, new Vector2(shape.Center.X, -shape.Center.Y - 50), shape.DistanceFromEntrance.ToString(), Color.White, Color.Black * 0.5f, font: GUI.LargeFont);
|
GUI.DrawRectangle(spriteBatch, drawRect, Color.Cyan, false, 0, 6);
|
||||||
}
|
|
||||||
foreach (Line line in walls)
|
|
||||||
{
|
|
||||||
GUI.DrawLine(spriteBatch, new Vector2(line.A.X, -line.A.Y), new Vector2(line.B.X, -line.B.Y), GUI.Style.Red, 0.0f, 10);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -846,16 +846,15 @@ namespace Barotrauma.Lights
|
|||||||
if (chList.Submarine == null)
|
if (chList.Submarine == null)
|
||||||
{
|
{
|
||||||
list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)));
|
list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)));
|
||||||
|
|
||||||
}
|
}
|
||||||
//light is outside, convexhull inside a sub
|
//light is outside, convexhull inside a sub
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Rectangle subBorders = chList.Submarine.Borders;
|
Rectangle subBorders = chList.Submarine.Borders;
|
||||||
subBorders.Y -= chList.Submarine.Borders.Height;
|
subBorders.Y -= chList.Submarine.Borders.Height;
|
||||||
if (!MathUtils.CircleIntersectsRectangle(lightPos - chList.Submarine.WorldPosition, range, subBorders)) continue;
|
if (!MathUtils.CircleIntersectsRectangle(lightPos - chList.Submarine.WorldPosition, range, subBorders)) { continue; }
|
||||||
|
|
||||||
lightPos -= (chList.Submarine.WorldPosition - chList.Submarine.HiddenSubPosition);
|
lightPos -= chList.Submarine.WorldPosition - chList.Submarine.HiddenSubPosition;
|
||||||
|
|
||||||
list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)));
|
list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)));
|
||||||
}
|
}
|
||||||
@@ -865,14 +864,6 @@ namespace Barotrauma.Lights
|
|||||||
//light is inside, convexhull outside
|
//light is inside, convexhull outside
|
||||||
if (chList.Submarine == null)
|
if (chList.Submarine == null)
|
||||||
{
|
{
|
||||||
lightPos += (ParentSub.WorldPosition - ParentSub.HiddenSubPosition);
|
|
||||||
HashSet<RuinGeneration.Ruin> visibleRuins = new HashSet<RuinGeneration.Ruin>();
|
|
||||||
foreach (RuinGeneration.Ruin ruin in Level.Loaded.Ruins)
|
|
||||||
{
|
|
||||||
if (!MathUtils.CircleIntersectsRectangle(lightPos, range, ruin.Area)) { continue; }
|
|
||||||
visibleRuins.Add(ruin);
|
|
||||||
}
|
|
||||||
list.AddRange(chList.List.FindAll(ch => ch.ParentEntity?.ParentRuin != null && visibleRuins.Contains(ch.ParentEntity.ParentRuin)));
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//light and convexhull are both inside the same sub
|
//light and convexhull are both inside the same sub
|
||||||
|
|||||||
@@ -197,7 +197,9 @@ namespace Barotrauma.Lights
|
|||||||
float spriteRange = Math.Max(
|
float spriteRange = Math.Max(
|
||||||
light.LightSprite.size.X * light.SpriteScale.X * (0.5f + Math.Abs(light.LightSprite.RelativeOrigin.X - 0.5f)),
|
light.LightSprite.size.X * light.SpriteScale.X * (0.5f + Math.Abs(light.LightSprite.RelativeOrigin.X - 0.5f)),
|
||||||
light.LightSprite.size.Y * light.SpriteScale.Y * (0.5f + Math.Abs(light.LightSprite.RelativeOrigin.Y - 0.5f)));
|
light.LightSprite.size.Y * light.SpriteScale.Y * (0.5f + Math.Abs(light.LightSprite.RelativeOrigin.Y - 0.5f)));
|
||||||
range = Math.Max(spriteRange, range);
|
|
||||||
|
float targetSize = Math.Max(light.LightTextureTargetSize.X, light.LightTextureTargetSize.Y);
|
||||||
|
range = Math.Max(Math.Max(spriteRange, targetSize), range);
|
||||||
}
|
}
|
||||||
if (!MathUtils.CircleIntersectsRectangle(light.WorldPosition, range, viewRect)) { continue; }
|
if (!MathUtils.CircleIntersectsRectangle(light.WorldPosition, range, viewRect)) { continue; }
|
||||||
activeLights.Add(light);
|
activeLights.Add(light);
|
||||||
@@ -238,13 +240,13 @@ namespace Barotrauma.Lights
|
|||||||
//draw a black rectangle on hulls to hide background lights behind subs
|
//draw a black rectangle on hulls to hide background lights behind subs
|
||||||
//---------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
if (backgroundObstructor != null)
|
/*if (backgroundObstructor != null)
|
||||||
{
|
{
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);
|
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);
|
||||||
spriteBatch.Draw(backgroundObstructor, new Rectangle(0, 0,
|
spriteBatch.Draw(backgroundObstructor, new Rectangle(0, 0,
|
||||||
(int)(GameMain.GraphicsWidth * currLightMapScale), (int)(GameMain.GraphicsHeight * currLightMapScale)), Color.Black);
|
(int)(GameMain.GraphicsWidth * currLightMapScale), (int)(GameMain.GraphicsHeight * currLightMapScale)), Color.Black);
|
||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
}
|
}*/
|
||||||
|
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, transformMatrix: spriteBatchTransform);
|
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, transformMatrix: spriteBatchTransform);
|
||||||
Dictionary<Hull, Rectangle> visibleHulls = GetVisibleHulls(cam);
|
Dictionary<Hull, Rectangle> visibleHulls = GetVisibleHulls(cam);
|
||||||
@@ -258,7 +260,7 @@ namespace Barotrauma.Lights
|
|||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
|
|
||||||
SolidColorEffect.CurrentTechnique = SolidColorEffect.Techniques["SolidColor"];
|
SolidColorEffect.CurrentTechnique = SolidColorEffect.Techniques["SolidColor"];
|
||||||
SolidColorEffect.Parameters["color"].SetValue(AmbientLight.ToVector4());
|
SolidColorEffect.Parameters["color"].SetValue(AmbientLight.Opaque().ToVector4());
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, transformMatrix: spriteBatchTransform, effect: SolidColorEffect);
|
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, transformMatrix: spriteBatchTransform, effect: SolidColorEffect);
|
||||||
Submarine.DrawDamageable(spriteBatch, null);
|
Submarine.DrawDamageable(spriteBatch, null);
|
||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
|
|||||||
@@ -376,6 +376,22 @@ namespace Barotrauma.Lights
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Vector2 lightTextureTargetSize;
|
||||||
|
|
||||||
|
public Vector2 LightTextureTargetSize
|
||||||
|
{
|
||||||
|
get => lightTextureTargetSize;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
NeedsRecalculation = true;
|
||||||
|
NeedsHullCheck = true;
|
||||||
|
lightTextureTargetSize = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 LightTextureOffset { get; set; }
|
||||||
|
public Vector2 LightTextureScale { get; set; } = Vector2.One;
|
||||||
|
|
||||||
public float TextureRange
|
public float TextureRange
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -1228,10 +1244,19 @@ namespace Barotrauma.Lights
|
|||||||
}
|
}
|
||||||
drawPos.Y = -drawPos.Y;
|
drawPos.Y = -drawPos.Y;
|
||||||
|
|
||||||
LightSprite.Draw(
|
Color color = new Color(Color, (lightSourceParams.OverrideLightSpriteAlpha ?? Color.A / 255.0f) * CurrentBrightness);
|
||||||
spriteBatch, drawPos,
|
|
||||||
new Color(Color, (lightSourceParams.OverrideLightSpriteAlpha ?? Color.A / 255.0f) * CurrentBrightness),
|
if (LightTextureTargetSize != Vector2.Zero)
|
||||||
origin, -Rotation + MathHelper.ToRadians(LightSourceParams.Rotation), SpriteScale, LightSpriteEffect);
|
{
|
||||||
|
LightSprite.DrawTiled(spriteBatch, drawPos, LightTextureTargetSize, color, startOffset: LightTextureOffset, textureScale: LightTextureScale);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LightSprite.Draw(
|
||||||
|
spriteBatch, drawPos,
|
||||||
|
color,
|
||||||
|
origin, -Rotation + MathHelper.ToRadians(LightSourceParams.Rotation), SpriteScale, LightSpriteEffect);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameMain.DebugDraw && Screen.Selected.Cam.Zoom > 0.1f)
|
if (GameMain.DebugDraw && Screen.Selected.Cam.Zoom > 0.1f)
|
||||||
@@ -1291,7 +1316,7 @@ namespace Barotrauma.Lights
|
|||||||
if (ParentSub != null) { drawPos += ParentSub.DrawPosition; }
|
if (ParentSub != null) { drawPos += ParentSub.DrawPosition; }
|
||||||
drawPos.Y = -drawPos.Y;
|
drawPos.Y = -drawPos.Y;
|
||||||
|
|
||||||
spriteBatch.Draw(currentTexture, drawPos, null, Color.Multiply(CurrentBrightness), -rotation, center, scale, SpriteEffects.None, 1);
|
spriteBatch.Draw(currentTexture, drawPos, null, Color.Multiply(CurrentBrightness), -rotation + MathHelper.ToRadians(LightSourceParams.Rotation), center, scale, SpriteEffects.None, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1318,7 +1343,7 @@ namespace Barotrauma.Lights
|
|||||||
Vector2 offset = ParentSub == null ? Vector2.Zero : ParentSub.DrawPosition;
|
Vector2 offset = ParentSub == null ? Vector2.Zero : ParentSub.DrawPosition;
|
||||||
lightEffect.World =
|
lightEffect.World =
|
||||||
Matrix.CreateTranslation(-new Vector3(position, 0.0f)) *
|
Matrix.CreateTranslation(-new Vector3(position, 0.0f)) *
|
||||||
Matrix.CreateRotationZ(rotateVertices) *
|
Matrix.CreateRotationZ(rotateVertices - MathHelper.ToRadians(LightSourceParams.Rotation)) *
|
||||||
Matrix.CreateTranslation(new Vector3(position + offset + translateVertices, 0.0f)) *
|
Matrix.CreateTranslation(new Vector3(position + offset + translateVertices, 0.0f)) *
|
||||||
transform;
|
transform;
|
||||||
|
|
||||||
|
|||||||
@@ -265,7 +265,7 @@ namespace Barotrauma
|
|||||||
if (!currentDisplayLocation.Discovered)
|
if (!currentDisplayLocation.Discovered)
|
||||||
{
|
{
|
||||||
RemoveFogOfWar(currentDisplayLocation);
|
RemoveFogOfWar(currentDisplayLocation);
|
||||||
currentDisplayLocation.Discovered = true;
|
currentDisplayLocation.Discover();
|
||||||
if (currentDisplayLocation.MapPosition.X > furthestDiscoveredLocation.MapPosition.X)
|
if (currentDisplayLocation.MapPosition.X > furthestDiscoveredLocation.MapPosition.X)
|
||||||
{
|
{
|
||||||
furthestDiscoveredLocation = currentDisplayLocation;
|
furthestDiscoveredLocation = currentDisplayLocation;
|
||||||
@@ -426,7 +426,7 @@ namespace Barotrauma
|
|||||||
Level.Loaded.DebugSetStartLocation(CurrentLocation);
|
Level.Loaded.DebugSetStartLocation(CurrentLocation);
|
||||||
Level.Loaded.DebugSetEndLocation(null);
|
Level.Loaded.DebugSetEndLocation(null);
|
||||||
|
|
||||||
CurrentLocation.Discovered = true;
|
CurrentLocation.Discover();
|
||||||
OnLocationChanged?.Invoke(prevLocation, CurrentLocation);
|
OnLocationChanged?.Invoke(prevLocation, CurrentLocation);
|
||||||
SelectLocation(-1);
|
SelectLocation(-1);
|
||||||
if (GameMain.Client == null)
|
if (GameMain.Client == null)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using Microsoft.Xna.Framework.Input;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Barotrauma.Lights;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -423,20 +424,24 @@ namespace Barotrauma
|
|||||||
|
|
||||||
//select wire if both items it's connected to are selected
|
//select wire if both items it's connected to are selected
|
||||||
var selectedItems = SelectedList.Where(e => e is Item).Cast<Item>().ToList();
|
var selectedItems = SelectedList.Where(e => e is Item).Cast<Item>().ToList();
|
||||||
foreach (Item item in selectedItems)
|
foreach (Item item in Item.ItemList)
|
||||||
{
|
{
|
||||||
if (item.Connections == null) continue;
|
var wire = item.GetComponent<Wire>();
|
||||||
foreach (Connection c in item.Connections)
|
if (wire == null) { continue; }
|
||||||
{
|
Item item0 = wire.Connections[0]?.Item;
|
||||||
foreach (Wire w in c.Wires)
|
Item item1 = wire.Connections[1]?.Item;
|
||||||
{
|
|
||||||
if (w == null || SelectedList.Contains(w.Item)) continue;
|
|
||||||
|
|
||||||
if (w.OtherConnection(c) != null && SelectedList.Contains(w.OtherConnection(c).Item))
|
if (item0 == null && item1 != null)
|
||||||
{
|
{
|
||||||
SelectedList.Add(w.Item);
|
item0 = Item.ItemList.Find(it => it.GetComponent<ConnectionPanel>()?.DisconnectedWires.Contains(wire) ?? false);
|
||||||
}
|
}
|
||||||
}
|
else if (item0 != null && item1 == null)
|
||||||
|
{
|
||||||
|
item1 = Item.ItemList.Find(it => it.GetComponent<ConnectionPanel>()?.DisconnectedWires.Contains(wire) ?? false);
|
||||||
|
}
|
||||||
|
if (item0 != null && item1 != null && SelectedList.Contains(item0) && SelectedList.Contains(item1))
|
||||||
|
{
|
||||||
|
SelectedList.Add(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -989,6 +994,10 @@ namespace Barotrauma
|
|||||||
clone.Move(moveAmount);
|
clone.Move(moveAmount);
|
||||||
clone.Submarine = Submarine.MainSub;
|
clone.Submarine = Submarine.MainSub;
|
||||||
}
|
}
|
||||||
|
foreach (MapEntity clone in SelectedList)
|
||||||
|
{
|
||||||
|
(clone as Item)?.GetComponent<ItemContainer>()?.SetContainedItemPositions();
|
||||||
|
}
|
||||||
|
|
||||||
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(clones, false, handleInventoryBehavior: false));
|
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(clones, false, handleInventoryBehavior: false));
|
||||||
}
|
}
|
||||||
@@ -1012,9 +1021,9 @@ namespace Barotrauma
|
|||||||
return newEntities;
|
return newEntities;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void AddToGUIUpdateList()
|
public virtual void AddToGUIUpdateList(int order = 0)
|
||||||
{
|
{
|
||||||
if (editingHUD != null && editingHUD.UserData == this) editingHUD.AddToGUIUpdateList();
|
if (editingHUD != null && editingHUD.UserData == this) { editingHUD.AddToGUIUpdateList(order: order); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void UpdateEditing(Camera cam, float deltaTime) { }
|
public virtual void UpdateEditing(Camera cam, float deltaTime) { }
|
||||||
@@ -1140,6 +1149,15 @@ namespace Barotrauma
|
|||||||
var oldData = new List<Rectangle> { prevRect.Value };
|
var oldData = new List<Rectangle> { prevRect.Value };
|
||||||
SubEditorScreen.StoreCommand(new TransformCommand(new List<MapEntity> { this }, newData, oldData, true));
|
SubEditorScreen.StoreCommand(new TransformCommand(new List<MapEntity> { this }, newData, oldData, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this is Structure structure)
|
||||||
|
{
|
||||||
|
foreach (LightSource light in structure.Lights)
|
||||||
|
{
|
||||||
|
light.LightTextureTargetSize = Rect.Size.ToVector2();
|
||||||
|
light.Position = rect.Location.ToVector2();
|
||||||
|
}
|
||||||
|
}
|
||||||
prevRect = null;
|
prevRect = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private readonly Dictionary<DecorativeSprite, DecorativeSprite.State> spriteAnimState = new Dictionary<DecorativeSprite, DecorativeSprite.State>();
|
private readonly Dictionary<DecorativeSprite, DecorativeSprite.State> spriteAnimState = new Dictionary<DecorativeSprite, DecorativeSprite.State>();
|
||||||
|
|
||||||
|
public readonly List<LightSource> Lights = new List<LightSource>();
|
||||||
|
|
||||||
public override bool SelectableInEditor
|
public override bool SelectableInEditor
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -91,6 +93,22 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetLightTextureOffset()
|
||||||
|
{
|
||||||
|
Vector2 textOffset = textureOffset;
|
||||||
|
if (FlippedX) { textOffset.X = -textOffset.X; }
|
||||||
|
if (FlippedY) { textOffset.Y = -textOffset.Y; }
|
||||||
|
|
||||||
|
foreach (LightSource light in Lights)
|
||||||
|
{
|
||||||
|
Vector2 bgOffset = new Vector2(
|
||||||
|
MathUtils.PositiveModulo((int)-textOffset.X, light.texture.Width),
|
||||||
|
MathUtils.PositiveModulo((int)-textOffset.Y, light.texture.Height));
|
||||||
|
|
||||||
|
light.LightTextureOffset = bgOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public GUIComponent CreateEditingHUD(bool inGame = false)
|
public GUIComponent CreateEditingHUD(bool inGame = false)
|
||||||
{
|
{
|
||||||
int heightScaled = (int)(20 * GUI.Scale);
|
int heightScaled = (int)(20 * GUI.Scale);
|
||||||
@@ -267,6 +285,8 @@ namespace Barotrauma
|
|||||||
//color = Color.Lerp(color, Color.Gold, 0.5f);
|
//color = Color.Lerp(color, Color.Gold, 0.5f);
|
||||||
color = spriteColor;
|
color = spriteColor;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Vector2 rectSize = rect.Size.ToVector2();
|
Vector2 rectSize = rect.Size.ToVector2();
|
||||||
if (BodyWidth > 0.0f) { rectSize.X = BodyWidth; }
|
if (BodyWidth > 0.0f) { rectSize.X = BodyWidth; }
|
||||||
if (BodyHeight > 0.0f) { rectSize.Y = BodyHeight; }
|
if (BodyHeight > 0.0f) { rectSize.Y = BodyHeight; }
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using Microsoft.Xna.Framework.Graphics;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
using Barotrauma.IO;
|
using Barotrauma.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
@@ -177,7 +178,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
//drawing ----------------------------------------------------
|
//drawing ----------------------------------------------------
|
||||||
private static readonly HashSet<Submarine> visibleSubs = new HashSet<Submarine>();
|
private static readonly HashSet<Submarine> visibleSubs = new HashSet<Submarine>();
|
||||||
private static readonly HashSet<Ruin> visibleRuins = new HashSet<Ruin>();
|
|
||||||
public static void CullEntities(Camera cam)
|
public static void CullEntities(Camera cam)
|
||||||
{
|
{
|
||||||
visibleSubs.Clear();
|
visibleSubs.Clear();
|
||||||
@@ -197,24 +197,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
visibleRuins.Clear();
|
|
||||||
if (Level.Loaded != null)
|
|
||||||
{
|
|
||||||
foreach (Ruin ruin in Level.Loaded.Ruins)
|
|
||||||
{
|
|
||||||
Rectangle worldBorders = new Rectangle(
|
|
||||||
ruin.Area.X - 500,
|
|
||||||
ruin.Area.Y + ruin.Area.Height + 500,
|
|
||||||
ruin.Area.Width + 1000,
|
|
||||||
ruin.Area.Height + 1000);
|
|
||||||
|
|
||||||
if (RectsOverlap(worldBorders, cam.WorldView))
|
|
||||||
{
|
|
||||||
visibleRuins.Add(ruin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (visibleEntities == null)
|
if (visibleEntities == null)
|
||||||
{
|
{
|
||||||
visibleEntities = new List<MapEntity>(MapEntity.mapEntityList.Count);
|
visibleEntities = new List<MapEntity>(MapEntity.mapEntityList.Count);
|
||||||
@@ -231,10 +213,6 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (!visibleSubs.Contains(entity.Submarine)) { continue; }
|
if (!visibleSubs.Contains(entity.Submarine)) { continue; }
|
||||||
}
|
}
|
||||||
else if (entity.ParentRuin != null)
|
|
||||||
{
|
|
||||||
if (!visibleRuins.Contains(entity.ParentRuin)) { continue; }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entity.IsVisible(worldView)) { visibleEntities.Add(entity); }
|
if (entity.IsVisible(worldView)) { visibleEntities.Add(entity); }
|
||||||
}
|
}
|
||||||
@@ -403,6 +381,8 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO remove
|
||||||
|
[Obsolete("Use MiniMap.CreateMiniMap()")]
|
||||||
public void CreateMiniMap(GUIComponent parent, IEnumerable<Entity> pointsOfInterest = null, bool ignoreOutpost = false)
|
public void CreateMiniMap(GUIComponent parent, IEnumerable<Entity> pointsOfInterest = null, bool ignoreOutpost = false)
|
||||||
{
|
{
|
||||||
Rectangle worldBorders = GetDockedBorders();
|
Rectangle worldBorders = GetDockedBorders();
|
||||||
@@ -417,24 +397,122 @@ namespace Barotrauma
|
|||||||
GUIFrame hullContainer = new GUIFrame(new RectTransform(
|
GUIFrame hullContainer = new GUIFrame(new RectTransform(
|
||||||
(parentAspectRatio > aspectRatio ? new Vector2(aspectRatio / parentAspectRatio, 1.0f) : new Vector2(1.0f, parentAspectRatio / aspectRatio)) * scale,
|
(parentAspectRatio > aspectRatio ? new Vector2(aspectRatio / parentAspectRatio, 1.0f) : new Vector2(1.0f, parentAspectRatio / aspectRatio)) * scale,
|
||||||
parent.RectTransform, Anchor.Center),
|
parent.RectTransform, Anchor.Center),
|
||||||
style: null);
|
style: null)
|
||||||
|
{
|
||||||
|
UserData = "hullcontainer"
|
||||||
|
};
|
||||||
|
|
||||||
var connectedSubs = GetConnectedSubs();
|
var connectedSubs = GetConnectedSubs();
|
||||||
foreach (Hull hull in Hull.hullList)
|
|
||||||
{
|
|
||||||
if (hull.Submarine != this && !connectedSubs.Contains(hull.Submarine)) { continue; }
|
|
||||||
if (ignoreOutpost && !IsEntityFoundOnThisSub(hull, true)) { continue; }
|
|
||||||
|
|
||||||
|
HashSet<Hull> hullList = Hull.hullList.Where(hull => hull.Submarine == this || connectedSubs.Contains(hull.Submarine)).Where(hull => !ignoreOutpost || IsEntityFoundOnThisSub(hull, true)).ToHashSet();
|
||||||
|
|
||||||
|
Dictionary<Hull, HashSet<Hull>> combinedHulls = new Dictionary<Hull, HashSet<Hull>>();
|
||||||
|
|
||||||
|
foreach (Hull hull in hullList)
|
||||||
|
{
|
||||||
|
if (combinedHulls.ContainsKey(hull) || combinedHulls.Values.Any(hh => hh.Contains(hull))) { continue; }
|
||||||
|
|
||||||
|
List<Hull> linkedHulls = new List<Hull>();
|
||||||
|
MiniMap.GetLinkedHulls(hull, linkedHulls);
|
||||||
|
|
||||||
|
linkedHulls.Remove(hull);
|
||||||
|
|
||||||
|
foreach (Hull linkedHull in linkedHulls)
|
||||||
|
{
|
||||||
|
if (!combinedHulls.ContainsKey(hull))
|
||||||
|
{
|
||||||
|
combinedHulls.Add(hull, new HashSet<Hull>());
|
||||||
|
}
|
||||||
|
|
||||||
|
combinedHulls[hull].Add(linkedHull);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Hull hull in hullList)
|
||||||
|
{
|
||||||
Vector2 relativeHullPos = new Vector2(
|
Vector2 relativeHullPos = new Vector2(
|
||||||
(hull.WorldRect.X - worldBorders.X) / (float)worldBorders.Width,
|
(hull.WorldRect.X - worldBorders.X) / (float)worldBorders.Width,
|
||||||
(worldBorders.Y - hull.WorldRect.Y) / (float)worldBorders.Height);
|
(worldBorders.Y - hull.WorldRect.Y) / (float)worldBorders.Height);
|
||||||
Vector2 relativeHullSize = new Vector2(hull.Rect.Width / (float)worldBorders.Width, hull.Rect.Height / (float)worldBorders.Height);
|
Vector2 relativeHullSize = new Vector2(hull.Rect.Width / (float)worldBorders.Width, hull.Rect.Height / (float)worldBorders.Height);
|
||||||
|
|
||||||
var hullFrame = new GUIFrame(new RectTransform(relativeHullSize, hullContainer.RectTransform) { RelativeOffset = relativeHullPos }, style: "MiniMapRoom", color: Color.DarkCyan * 0.8f)
|
bool hideHull = combinedHulls.ContainsKey(hull) || combinedHulls.Values.Any(hh => hh.Contains(hull));
|
||||||
|
|
||||||
|
if (hideHull) { continue; }
|
||||||
|
|
||||||
|
Color color = Color.DarkCyan * 0.8f;
|
||||||
|
|
||||||
|
var hullFrame = new GUIFrame(new RectTransform(relativeHullSize, hullContainer.RectTransform) { RelativeOffset = relativeHullPos }, style: "MiniMapRoom", color: color)
|
||||||
{
|
{
|
||||||
UserData = hull
|
UserData = hull
|
||||||
};
|
};
|
||||||
new GUIFrame(new RectTransform(Vector2.One, hullFrame.RectTransform), style: "ScanLines", color: Color.DarkCyan * 0.8f);
|
|
||||||
|
new GUIFrame(new RectTransform(Vector2.One, hullFrame.RectTransform), style: "ScanLines", color: color);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var (mainHull, linkedHulls) in combinedHulls)
|
||||||
|
{
|
||||||
|
MiniMapHullData data = ConstructLinkedHulls(mainHull, linkedHulls, hullContainer, worldBorders);
|
||||||
|
|
||||||
|
Vector2 relativeHullPos = new Vector2(
|
||||||
|
(data.Bounds.X - worldBorders.X) / worldBorders.Width,
|
||||||
|
(worldBorders.Y - data.Bounds.Y) / worldBorders.Height);
|
||||||
|
|
||||||
|
Vector2 relativeHullSize = new Vector2(data.Bounds.Width / worldBorders.Width, data.Bounds.Height / worldBorders.Height);
|
||||||
|
|
||||||
|
Color color = Color.DarkCyan * 0.8f;
|
||||||
|
|
||||||
|
float highestY = 0f,
|
||||||
|
highestX = 0f;
|
||||||
|
|
||||||
|
foreach (var (r, _) in data.RectDatas)
|
||||||
|
{
|
||||||
|
float y = r.Y - -r.Height,
|
||||||
|
x = r.X;
|
||||||
|
|
||||||
|
if (y > highestY) { highestY = y; }
|
||||||
|
if (x > highestX) { highestX = x; }
|
||||||
|
}
|
||||||
|
|
||||||
|
HashSet<GUIFrame> frames = new HashSet<GUIFrame>();
|
||||||
|
|
||||||
|
foreach (var (snappredRect, hull) in data.RectDatas)
|
||||||
|
{
|
||||||
|
RectangleF rect = snappredRect;
|
||||||
|
rect.Height = -rect.Height;
|
||||||
|
rect.Y -= rect.Height;
|
||||||
|
|
||||||
|
var (parentW, parentH) = hullContainer.Rect.Size.ToVector2();
|
||||||
|
Vector2 size = new Vector2(rect.Width / parentW, rect.Height / parentH);
|
||||||
|
// TODO this won't be required if we some day switch RectTransform to use RectangleF
|
||||||
|
Vector2 pos = new Vector2(rect.X / parentW, rect.Y / parentH);
|
||||||
|
|
||||||
|
GUIFrame hullFrame = new GUIFrame(new RectTransform(size, hullContainer.RectTransform) { RelativeOffset = pos }, style: "ScanLinesSeamless", color: color)
|
||||||
|
{
|
||||||
|
UserData = hull,
|
||||||
|
UVOffset = new Vector2(highestX - rect.X, highestY - rect.Y)
|
||||||
|
};
|
||||||
|
|
||||||
|
frames.Add(hullFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
new GUICustomComponent(new RectTransform(relativeHullSize, hullContainer.RectTransform) { RelativeOffset = relativeHullPos }, (spriteBatch, component) =>
|
||||||
|
{
|
||||||
|
foreach (List<Vector2> list in data.Polygon)
|
||||||
|
{
|
||||||
|
spriteBatch.DrawPolygonInner(hullContainer.Rect.Location.ToVector2(), list, component.Color, 2f);
|
||||||
|
}
|
||||||
|
}, (deltaTime, component) =>
|
||||||
|
{
|
||||||
|
if (component.Parent.Rect.Size != data.ParentSize)
|
||||||
|
{
|
||||||
|
data = ConstructLinkedHulls(mainHull, linkedHulls, hullContainer, worldBorders);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
{
|
||||||
|
UserData = frames,
|
||||||
|
Color = color,
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pointsOfInterest != null)
|
if (pointsOfInterest != null)
|
||||||
@@ -453,6 +531,64 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static MiniMapHullData ConstructLinkedHulls(Hull mainHull, HashSet<Hull> linkedHulls, GUIComponent parent, Rectangle worldBorders)
|
||||||
|
{
|
||||||
|
Rectangle parentRect = parent.Rect;
|
||||||
|
|
||||||
|
Dictionary<Hull, Rectangle> rects = new Dictionary<Hull, Rectangle>();
|
||||||
|
Rectangle worldRect = mainHull.WorldRect;
|
||||||
|
worldRect.Y = -worldRect.Y;
|
||||||
|
|
||||||
|
rects.Add(mainHull, worldRect);
|
||||||
|
|
||||||
|
foreach (Hull hull in linkedHulls)
|
||||||
|
{
|
||||||
|
Rectangle rect = hull.WorldRect;
|
||||||
|
rect.Y = -rect.Y;
|
||||||
|
|
||||||
|
worldRect = Rectangle.Union(worldRect, rect);
|
||||||
|
rects.Add(hull, rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
worldRect.Y = -worldRect.Y;
|
||||||
|
|
||||||
|
List<RectangleF> normalizedRects = new List<RectangleF>();
|
||||||
|
List<Hull> hullRefs = new List<Hull>();
|
||||||
|
foreach (var (hull, rect) in rects)
|
||||||
|
{
|
||||||
|
Rectangle wRect = rect;
|
||||||
|
wRect.Y = -wRect.Y;
|
||||||
|
|
||||||
|
var (posX, posY) = new Vector2(
|
||||||
|
(wRect.X - worldBorders.X) / (float)worldBorders.Width,
|
||||||
|
(worldBorders.Y - wRect.Y) / (float)worldBorders.Height);
|
||||||
|
|
||||||
|
var (scaleX, scaleY) = new Vector2(wRect.Width / (float)worldBorders.Width, wRect.Height / (float)worldBorders.Height);
|
||||||
|
|
||||||
|
RectangleF newRect = new RectangleF(posX * parentRect.Width, posY * parentRect.Height, scaleX * parentRect.Width, scaleY * parentRect.Height);
|
||||||
|
|
||||||
|
normalizedRects.Add(newRect);
|
||||||
|
hullRefs.Add(hull);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImmutableArray<RectangleF> snappedRectangles = ToolBox.SnapRectangles(normalizedRects, treshold: 1);
|
||||||
|
|
||||||
|
List<List<Vector2>> polygon = ToolBox.CombineRectanglesIntoShape(snappedRectangles);
|
||||||
|
|
||||||
|
List<List<Vector2>> scaledPolygon = new List<List<Vector2>>();
|
||||||
|
|
||||||
|
foreach (List<Vector2> list in polygon)
|
||||||
|
{
|
||||||
|
var (polySizeX, polySizeY) = ToolBox.GetPolygonBoundingBoxSize(list);
|
||||||
|
float sizeX = polySizeX - 1f,
|
||||||
|
sizeY = polySizeY - 1f;
|
||||||
|
|
||||||
|
scaledPolygon.Add(ToolBox.ScalePolygon(list, new Vector2(sizeX / polySizeX, sizeY / polySizeY)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new MiniMapHullData(scaledPolygon, worldRect, parentRect.Size, snappedRectangles, hullRefs.ToImmutableArray());
|
||||||
|
}
|
||||||
|
|
||||||
public void CheckForErrors()
|
public void CheckForErrors()
|
||||||
{
|
{
|
||||||
List<string> errorMsgs = new List<string>();
|
List<string> errorMsgs = new List<string>();
|
||||||
|
|||||||
@@ -600,6 +600,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
var prevScissorRect = GameMain.Instance.GraphicsDevice.ScissorRectangle;
|
var prevScissorRect = GameMain.Instance.GraphicsDevice.ScissorRectangle;
|
||||||
GameMain.Instance.GraphicsDevice.ScissorRectangle = scissorRectangle;
|
GameMain.Instance.GraphicsDevice.ScissorRectangle = scissorRectangle;
|
||||||
|
var prevRasterizerState = GameMain.Instance.GraphicsDevice.RasterizerState;
|
||||||
|
GameMain.Instance.GraphicsDevice.RasterizerState = GameMain.ScissorTestEnable;
|
||||||
|
|
||||||
spriteRecorder.Render(camera);
|
spriteRecorder.Render(camera);
|
||||||
|
|
||||||
@@ -643,6 +645,7 @@ namespace Barotrauma
|
|||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
|
|
||||||
GameMain.Instance.GraphicsDevice.ScissorRectangle = prevScissorRect;
|
GameMain.Instance.GraphicsDevice.ScissorRectangle = prevScissorRect;
|
||||||
|
GameMain.Instance.GraphicsDevice.RasterizerState = prevRasterizerState;
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred);
|
spriteBatch.Begin(SpriteSortMode.Deferred);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -127,6 +127,13 @@ namespace Barotrauma
|
|||||||
ID.ToString(),
|
ID.ToString(),
|
||||||
new Vector2(DrawPosition.X - 10, -DrawPosition.Y - 30),
|
new Vector2(DrawPosition.X - 10, -DrawPosition.Y - 30),
|
||||||
color);
|
color);
|
||||||
|
if (Tunnel?.Type != null)
|
||||||
|
{
|
||||||
|
GUI.SmallFont.DrawString(spriteBatch,
|
||||||
|
Tunnel.Type.ToString(),
|
||||||
|
new Vector2(DrawPosition.X - 10, -DrawPosition.Y - 45),
|
||||||
|
color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool IsMouseOn(Vector2 position)
|
public override bool IsMouseOn(Vector2 position)
|
||||||
@@ -164,10 +171,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
foreach (MapEntity e in mapEntityList)
|
foreach (MapEntity e in mapEntityList)
|
||||||
{
|
{
|
||||||
if (e.GetType() != typeof(WayPoint)) continue;
|
if (!(e is WayPoint) || e == this || !e.IsHighlighted) { continue; }
|
||||||
if (e == this) continue;
|
|
||||||
|
|
||||||
if (!Submarine.RectContains(e.Rect, position)) continue;
|
|
||||||
|
|
||||||
if (linkedTo.Contains(e))
|
if (linkedTo.Contains(e))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -64,7 +64,10 @@ namespace Barotrauma.Networking
|
|||||||
string orderOption = orderMessageInfo.OrderOption;
|
string orderOption = orderMessageInfo.OrderOption;
|
||||||
orderOption ??= orderMessageInfo.OrderOptionIndex.HasValue && orderMessageInfo.OrderOptionIndex >= 0 && orderMessageInfo.OrderOptionIndex < orderPrefab.Options.Length ?
|
orderOption ??= orderMessageInfo.OrderOptionIndex.HasValue && orderMessageInfo.OrderOptionIndex >= 0 && orderMessageInfo.OrderOptionIndex < orderPrefab.Options.Length ?
|
||||||
orderPrefab.Options[orderMessageInfo.OrderOptionIndex.Value] : "";
|
orderPrefab.Options[orderMessageInfo.OrderOptionIndex.Value] : "";
|
||||||
txt = orderPrefab.GetChatMessage(orderMessageInfo.TargetCharacter?.Name, senderCharacter?.CurrentHull?.DisplayName, givingOrderToSelf: orderMessageInfo.TargetCharacter == senderCharacter, orderOption: orderOption);
|
txt = orderPrefab.GetChatMessage(orderMessageInfo.TargetCharacter?.Name, senderCharacter?.CurrentHull?.DisplayName,
|
||||||
|
givingOrderToSelf: orderMessageInfo.TargetCharacter == senderCharacter,
|
||||||
|
orderOption: orderOption,
|
||||||
|
priority: orderMessageInfo.Priority);
|
||||||
|
|
||||||
if (GameMain.Client.GameStarted && Screen.Selected == GameMain.GameScreen)
|
if (GameMain.Client.GameStarted && Screen.Selected == GameMain.GameScreen)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -550,6 +550,13 @@ namespace Barotrauma.Networking
|
|||||||
okButton.OnClicked += msgBox.Close;
|
okButton.OnClicked += msgBox.Close;
|
||||||
var cancelButton = msgBox.Buttons[1];
|
var cancelButton = msgBox.Buttons[1];
|
||||||
cancelButton.OnClicked += msgBox.Close;
|
cancelButton.OnClicked += msgBox.Close;
|
||||||
|
passwordBox.OnEnterPressed += (GUITextBox textBox, string text) =>
|
||||||
|
{
|
||||||
|
msgBox.Close();
|
||||||
|
clientPeer?.SendPassword(passwordBox.Text);
|
||||||
|
requiresPw = false;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
okButton.OnClicked += (GUIButton button, object obj) =>
|
okButton.OnClicked += (GUIButton button, object obj) =>
|
||||||
{
|
{
|
||||||
@@ -565,6 +572,8 @@ namespace Barotrauma.Networking
|
|||||||
GameMain.ServerListScreen.Select();
|
GameMain.ServerListScreen.Select();
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
yield return CoroutineStatus.Running;
|
||||||
|
passwordBox.Select();
|
||||||
|
|
||||||
while (GUIMessageBox.MessageBoxes.Contains(msgBox))
|
while (GUIMessageBox.MessageBoxes.Contains(msgBox))
|
||||||
{
|
{
|
||||||
@@ -1456,6 +1465,7 @@ namespace Barotrauma.Networking
|
|||||||
bool respawnAllowed = inc.ReadBoolean();
|
bool respawnAllowed = inc.ReadBoolean();
|
||||||
serverSettings.AllowDisguises = inc.ReadBoolean();
|
serverSettings.AllowDisguises = inc.ReadBoolean();
|
||||||
serverSettings.AllowRewiring = inc.ReadBoolean();
|
serverSettings.AllowRewiring = inc.ReadBoolean();
|
||||||
|
serverSettings.AllowFriendlyFire = inc.ReadBoolean();
|
||||||
serverSettings.LockAllDefaultWires = inc.ReadBoolean();
|
serverSettings.LockAllDefaultWires = inc.ReadBoolean();
|
||||||
serverSettings.AllowRagdollButton = inc.ReadBoolean();
|
serverSettings.AllowRagdollButton = inc.ReadBoolean();
|
||||||
GameMain.NetLobbyScreen.UsingShuttle = inc.ReadBoolean();
|
GameMain.NetLobbyScreen.UsingShuttle = inc.ReadBoolean();
|
||||||
@@ -2746,6 +2756,9 @@ namespace Barotrauma.Networking
|
|||||||
msg.Write((byte)characterInfo.BeardIndex);
|
msg.Write((byte)characterInfo.BeardIndex);
|
||||||
msg.Write((byte)characterInfo.MoustacheIndex);
|
msg.Write((byte)characterInfo.MoustacheIndex);
|
||||||
msg.Write((byte)characterInfo.FaceAttachmentIndex);
|
msg.Write((byte)characterInfo.FaceAttachmentIndex);
|
||||||
|
msg.WriteColorR8G8B8(characterInfo.SkinColor);
|
||||||
|
msg.WriteColorR8G8B8(characterInfo.HairColor);
|
||||||
|
msg.WriteColorR8G8B8(characterInfo.FacialHairColor);
|
||||||
|
|
||||||
var jobPreferences = GameMain.NetLobbyScreen.JobPreferences;
|
var jobPreferences = GameMain.NetLobbyScreen.JobPreferences;
|
||||||
int count = Math.Min(jobPreferences.Count, 3);
|
int count = Math.Min(jobPreferences.Count, 3);
|
||||||
|
|||||||
+1
-1
@@ -288,7 +288,7 @@ namespace Barotrauma.Networking
|
|||||||
heartbeatTimer = 5.0;
|
heartbeatTimer = 5.0;
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
CoroutineManager.InvokeAfter(() =>
|
CoroutineManager.Invoke(() =>
|
||||||
{
|
{
|
||||||
if (GameMain.Client == null) { return; }
|
if (GameMain.Client == null) { return; }
|
||||||
if (Rand.Range(0.0f, 1.0f) < GameMain.Client.SimulatedLoss && sendType != Steamworks.P2PSend.Reliable) { return; }
|
if (Rand.Range(0.0f, 1.0f) < GameMain.Client.SimulatedLoss && sendType != Steamworks.P2PSend.Reliable) { return; }
|
||||||
|
|||||||
@@ -110,12 +110,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
if (frame == null) { return; }
|
if (frame == null) { return; }
|
||||||
|
|
||||||
var previewContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.98f), frame.RectTransform, Anchor.Center))
|
var title = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), frame.RectTransform), ServerName, font: GUI.LargeFont)
|
||||||
{
|
|
||||||
Stretch = true
|
|
||||||
};
|
|
||||||
|
|
||||||
var title = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), previewContainer.RectTransform, Anchor.CenterLeft), ServerName, font: GUI.LargeFont)
|
|
||||||
{
|
{
|
||||||
ToolTip = ServerName
|
ToolTip = ServerName
|
||||||
};
|
};
|
||||||
@@ -141,41 +136,30 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), previewContainer.RectTransform),
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), frame.RectTransform),
|
||||||
TextManager.AddPunctuation(':', TextManager.Get("ServerListVersion"), string.IsNullOrEmpty(GameVersion) ? TextManager.Get("Unknown") : GameVersion));
|
TextManager.AddPunctuation(':', TextManager.Get("ServerListVersion"), string.IsNullOrEmpty(GameVersion) ? TextManager.Get("Unknown") : GameVersion));
|
||||||
|
|
||||||
bool hidePlaystyleBanner = previewContainer.Rect.Height < 380 || !PlayStyle.HasValue;
|
bool hidePlaystyleBanner = !PlayStyle.HasValue;
|
||||||
if (!hidePlaystyleBanner)
|
if (!hidePlaystyleBanner)
|
||||||
{
|
{
|
||||||
PlayStyle playStyle = PlayStyle ?? Networking.PlayStyle.Serious;
|
PlayStyle playStyle = PlayStyle ?? Networking.PlayStyle.Serious;
|
||||||
Sprite playStyleBannerSprite = ServerListScreen.PlayStyleBanners[(int)playStyle];
|
Sprite playStyleBannerSprite = ServerListScreen.PlayStyleBanners[(int)playStyle];
|
||||||
float playStyleBannerAspectRatio = playStyleBannerSprite.SourceRect.Width / playStyleBannerSprite.SourceRect.Height;
|
float playStyleBannerAspectRatio = playStyleBannerSprite.SourceRect.Width / playStyleBannerSprite.SourceRect.Height;
|
||||||
var playStyleBanner = new GUIImage(new RectTransform(new Point(previewContainer.Rect.Width, (int)(previewContainer.Rect.Width / playStyleBannerAspectRatio)), previewContainer.RectTransform),
|
var playStyleBanner = new GUIImage(new RectTransform(new Point(frame.Rect.Width, (int)(frame.Rect.Width / playStyleBannerAspectRatio)), frame.RectTransform),
|
||||||
playStyleBannerSprite, null, true);
|
playStyleBannerSprite, null, true);
|
||||||
|
|
||||||
var playStyleName = new GUITextBlock(new RectTransform(new Vector2(0.15f, 0.0f), playStyleBanner.RectTransform) { RelativeOffset = new Vector2(0.01f, 0.06f) },
|
var playStyleName = new GUITextBlock(new RectTransform(new Vector2(0.15f, 0.0f), playStyleBanner.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.06f) },
|
||||||
TextManager.AddPunctuation(':', TextManager.Get("serverplaystyle"), TextManager.Get("servertag."+ playStyle)), textColor: Color.White,
|
TextManager.AddPunctuation(':', TextManager.Get("serverplaystyle"), TextManager.Get("servertag."+ playStyle)), textColor: Color.White,
|
||||||
font: GUI.SmallFont, textAlignment: Alignment.Center,
|
font: GUI.SmallFont, textAlignment: Alignment.Center,
|
||||||
color: ServerListScreen.PlayStyleColors[(int)playStyle], style: "GUISlopedHeader");
|
color: ServerListScreen.PlayStyleColors[(int)playStyle], style: "GUISlopedHeader");
|
||||||
playStyleName.RectTransform.NonScaledSize = (playStyleName.Font.MeasureString(playStyleName.Text) + new Vector2(20, 5) * GUI.Scale).ToPoint();
|
playStyleName.RectTransform.NonScaledSize = (playStyleName.Font.MeasureString(playStyleName.Text) + new Vector2(20, 5) * GUI.Scale).ToPoint();
|
||||||
playStyleName.RectTransform.IsFixedSize = true;
|
playStyleName.RectTransform.IsFixedSize = true;
|
||||||
|
|
||||||
var serverTypeContainer = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.2f), playStyleBanner.RectTransform, Anchor.BottomLeft, Pivot.BottomLeft),
|
|
||||||
"MainMenuNotifBackground", Color.Black)
|
|
||||||
{
|
|
||||||
CanBeFocused = false,
|
|
||||||
};
|
|
||||||
|
|
||||||
var serverType = new GUITextBlock(new RectTransform(Vector2.One, serverTypeContainer.RectTransform, Anchor.CenterLeft),
|
|
||||||
TextManager.Get((OwnerID != 0 || LobbyID != 0) ? "SteamP2PServer" : "DedicatedServer"), textAlignment: Alignment.CenterLeft);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var serverType = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), previewContainer.RectTransform, Anchor.CenterLeft),
|
|
||||||
TextManager.Get((OwnerID != 0 || LobbyID != 0) ? "SteamP2PServer" : "DedicatedServer"), textAlignment: Alignment.CenterLeft);
|
|
||||||
}
|
}
|
||||||
|
var serverType = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), frame.RectTransform),
|
||||||
|
TextManager.Get((OwnerID != 0 || LobbyID != 0) ? "SteamP2PServer" : "DedicatedServer"), textAlignment: Alignment.TopLeft);
|
||||||
|
serverType.RectTransform.MinSize = new Point(0, (int)(serverType.Rect.Height * 1.5f));
|
||||||
|
|
||||||
var content = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.6f), previewContainer.RectTransform))
|
var content = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.6f), frame.RectTransform))
|
||||||
{
|
{
|
||||||
Stretch = true
|
Stretch = true
|
||||||
};
|
};
|
||||||
@@ -285,7 +269,6 @@ namespace Barotrauma.Networking
|
|||||||
else
|
else
|
||||||
usingWhiteList.Selected = UsingWhiteList.Value;
|
usingWhiteList.Selected = UsingWhiteList.Value;
|
||||||
|
|
||||||
|
|
||||||
content.RectTransform.SizeChanged += () =>
|
content.RectTransform.SizeChanged += () =>
|
||||||
{
|
{
|
||||||
GUITextBlock.AutoScaleAndNormalize(allowSpectating.TextBlock, allowRespawn.TextBlock, usingWhiteList.TextBlock);
|
GUITextBlock.AutoScaleAndNormalize(allowSpectating.TextBlock, allowRespawn.TextBlock, usingWhiteList.TextBlock);
|
||||||
@@ -294,7 +277,7 @@ namespace Barotrauma.Networking
|
|||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform),
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform),
|
||||||
TextManager.Get("ServerListContentPackages"), textAlignment: Alignment.Center, font: GUI.SubHeadingFont);
|
TextManager.Get("ServerListContentPackages"), textAlignment: Alignment.Center, font: GUI.SubHeadingFont);
|
||||||
|
|
||||||
var contentPackageList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.2f), content.RectTransform)) { ScrollBarVisible = true };
|
var contentPackageList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.3f), frame.RectTransform)) { ScrollBarVisible = true };
|
||||||
if (ContentPackageNames.Count == 0)
|
if (ContentPackageNames.Count == 0)
|
||||||
{
|
{
|
||||||
new GUITextBlock(new RectTransform(Vector2.One, contentPackageList.Content.RectTransform), TextManager.Get("Unknown"), textAlignment: Alignment.Center)
|
new GUITextBlock(new RectTransform(Vector2.One, contentPackageList.Content.RectTransform), TextManager.Get("Unknown"), textAlignment: Alignment.Center)
|
||||||
@@ -309,7 +292,7 @@ namespace Barotrauma.Networking
|
|||||||
var packageText = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.15f), contentPackageList.Content.RectTransform) { MinSize = new Point(0, 15) },
|
var packageText = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.15f), contentPackageList.Content.RectTransform) { MinSize = new Point(0, 15) },
|
||||||
ContentPackageNames[i])
|
ContentPackageNames[i])
|
||||||
{
|
{
|
||||||
Enabled = false
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
if (i < ContentPackageHashes.Count)
|
if (i < ContentPackageHashes.Count)
|
||||||
{
|
{
|
||||||
@@ -322,7 +305,7 @@ namespace Barotrauma.Networking
|
|||||||
//workshop download link found
|
//workshop download link found
|
||||||
if (i < ContentPackageWorkshopIds.Count && ContentPackageWorkshopIds[i] != 0)
|
if (i < ContentPackageWorkshopIds.Count && ContentPackageWorkshopIds[i] != 0)
|
||||||
{
|
{
|
||||||
packageText.TextColor = Color.Yellow;
|
packageText.TextColor = GUI.Style.Yellow;
|
||||||
packageText.ToolTip = TextManager.GetWithVariable("ServerListIncompatibleContentPackageWorkshopAvailable", "[contentpackage]", ContentPackageNames[i]);
|
packageText.ToolTip = TextManager.GetWithVariable("ServerListIncompatibleContentPackageWorkshopAvailable", "[contentpackage]", ContentPackageNames[i]);
|
||||||
}
|
}
|
||||||
else //no package or workshop download link found, tough luck
|
else //no package or workshop download link found, tough luck
|
||||||
|
|||||||
@@ -1207,7 +1207,7 @@ namespace Barotrauma.Steam
|
|||||||
foreach (string file in allPackageFiles)
|
foreach (string file in allPackageFiles)
|
||||||
{
|
{
|
||||||
if (file == metaDataFilePath) { continue; }
|
if (file == metaDataFilePath) { continue; }
|
||||||
string relativePath = UpdaterUtil.GetRelativePath(file, item.Directory);
|
string relativePath = Path.GetRelativePath(item.Directory, file);
|
||||||
string fullPath = Path.GetFullPath(relativePath);
|
string fullPath = Path.GetFullPath(relativePath);
|
||||||
if (contentPackage.Files.Any(f => { string fp = Path.GetFullPath(f.Path); return fp == fullPath; })) { continue; }
|
if (contentPackage.Files.Any(f => { string fp = Path.GetFullPath(f.Path); return fp == fullPath; })) { continue; }
|
||||||
nonContentFiles.Add(relativePath);
|
nonContentFiles.Add(relativePath);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Microsoft.Xna.Framework;
|
|||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection.Metadata;
|
|
||||||
|
|
||||||
namespace Barotrauma.Particles
|
namespace Barotrauma.Particles
|
||||||
{
|
{
|
||||||
@@ -16,6 +15,8 @@ namespace Barotrauma.Particles
|
|||||||
public delegate void OnChangeHullHandler(Vector2 position, Hull currentHull);
|
public delegate void OnChangeHullHandler(Vector2 position, Hull currentHull);
|
||||||
public OnChangeHullHandler OnChangeHull;
|
public OnChangeHullHandler OnChangeHull;
|
||||||
|
|
||||||
|
public OnChangeHullHandler OnCollision;
|
||||||
|
|
||||||
private Vector2 position;
|
private Vector2 position;
|
||||||
private Vector2 prevPosition;
|
private Vector2 prevPosition;
|
||||||
|
|
||||||
@@ -166,6 +167,7 @@ namespace Barotrauma.Particles
|
|||||||
HighQualityCollisionDetection = false;
|
HighQualityCollisionDetection = false;
|
||||||
|
|
||||||
OnChangeHull = null;
|
OnChangeHull = null;
|
||||||
|
OnCollision = null;
|
||||||
|
|
||||||
subEmitters.Clear();
|
subEmitters.Clear();
|
||||||
hasSubEmitters = false;
|
hasSubEmitters = false;
|
||||||
@@ -340,12 +342,20 @@ namespace Barotrauma.Particles
|
|||||||
Vector2 collisionNormal = Vector2.Zero;
|
Vector2 collisionNormal = Vector2.Zero;
|
||||||
if (velocity.Y < 0.0f && position.Y - prefab.CollisionRadius * size.Y < hullRect.Y - hullRect.Height)
|
if (velocity.Y < 0.0f && position.Y - prefab.CollisionRadius * size.Y < hullRect.Y - hullRect.Height)
|
||||||
{
|
{
|
||||||
if (prefab.DeleteOnCollision) { return UpdateResult.Delete; }
|
if (prefab.DeleteOnCollision)
|
||||||
|
{
|
||||||
|
OnCollision?.Invoke(position, currentHull);
|
||||||
|
return UpdateResult.Delete;
|
||||||
|
}
|
||||||
collisionNormal = new Vector2(0.0f, 1.0f);
|
collisionNormal = new Vector2(0.0f, 1.0f);
|
||||||
}
|
}
|
||||||
else if (velocity.Y > 0.0f && position.Y + prefab.CollisionRadius * size.Y > hullRect.Y)
|
else if (velocity.Y > 0.0f && position.Y + prefab.CollisionRadius * size.Y > hullRect.Y)
|
||||||
{
|
{
|
||||||
if (prefab.DeleteOnCollision) { return UpdateResult.Delete; }
|
if (prefab.DeleteOnCollision)
|
||||||
|
{
|
||||||
|
OnCollision?.Invoke(position, currentHull);
|
||||||
|
return UpdateResult.Delete;
|
||||||
|
}
|
||||||
collisionNormal = new Vector2(0.0f, -1.0f);
|
collisionNormal = new Vector2(0.0f, -1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,6 +378,7 @@ namespace Barotrauma.Particles
|
|||||||
handleCollision(gapFound, collisionNormal);
|
handleCollision(gapFound, collisionNormal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
collisionNormal = Vector2.Zero;
|
||||||
if (velocity.X < 0.0f && position.X - prefab.CollisionRadius * size.X < hullRect.X)
|
if (velocity.X < 0.0f && position.X - prefab.CollisionRadius * size.X < hullRect.X)
|
||||||
{
|
{
|
||||||
if (prefab.DeleteOnCollision) { return UpdateResult.Delete; }
|
if (prefab.DeleteOnCollision) { return UpdateResult.Delete; }
|
||||||
@@ -487,6 +498,8 @@ namespace Barotrauma.Particles
|
|||||||
velocity.Y = Math.Sign(collisionNormal.Y) * Math.Abs(velocity.Y) * prefab.Restitution;
|
velocity.Y = Math.Sign(collisionNormal.Y) * Math.Abs(velocity.Y) * prefab.Restitution;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OnCollision?.Invoke(position, currentHull);
|
||||||
|
|
||||||
velocity += subVel;
|
velocity += subVel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,6 +536,8 @@ namespace Barotrauma.Particles
|
|||||||
velocity.Y *= (1.0f - prefab.Friction);
|
velocity.Y *= (1.0f - prefab.Friction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OnCollision?.Invoke(position, currentHull);
|
||||||
|
|
||||||
velocity *= prefab.Restitution;
|
velocity *= prefab.Restitution;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -138,6 +138,8 @@ namespace Barotrauma.Particles
|
|||||||
|
|
||||||
public void Emit(float deltaTime, Vector2 position, Hull hullGuess = null, float angle = 0.0f, float particleRotation = 0.0f, float velocityMultiplier = 1.0f, float sizeMultiplier = 1.0f, float amountMultiplier = 1.0f, Color? colorMultiplier = null, ParticlePrefab overrideParticle = null, Tuple<Vector2, Vector2> tracerPoints = null)
|
public void Emit(float deltaTime, Vector2 position, Hull hullGuess = null, float angle = 0.0f, float particleRotation = 0.0f, float velocityMultiplier = 1.0f, float sizeMultiplier = 1.0f, float amountMultiplier = 1.0f, Color? colorMultiplier = null, ParticlePrefab overrideParticle = null, Tuple<Vector2, Vector2> tracerPoints = null)
|
||||||
{
|
{
|
||||||
|
if (GameMain.Client?.MidRoundSyncing ?? false) { return; }
|
||||||
|
|
||||||
if (initialDelay < Prefab.Properties.InitialDelay)
|
if (initialDelay < Prefab.Properties.InitialDelay)
|
||||||
{
|
{
|
||||||
initialDelay += deltaTime;
|
initialDelay += deltaTime;
|
||||||
|
|||||||
@@ -133,22 +133,41 @@ namespace Barotrauma.Particles
|
|||||||
|
|
||||||
public Particle CreateParticle(ParticlePrefab prefab, Vector2 position, Vector2 velocity, float rotation = 0.0f, Hull hullGuess = null, bool drawOnTop = false, float collisionIgnoreTimer = 0f, Tuple<Vector2, Vector2> tracerPoints = null)
|
public Particle CreateParticle(ParticlePrefab prefab, Vector2 position, Vector2 velocity, float rotation = 0.0f, Hull hullGuess = null, bool drawOnTop = false, float collisionIgnoreTimer = 0f, Tuple<Vector2, Vector2> tracerPoints = null)
|
||||||
{
|
{
|
||||||
if (particleCount >= MaxParticles || prefab == null || prefab.Sprites.Count == 0) { return null; }
|
if (prefab == null || prefab.Sprites.Count == 0) { return null; }
|
||||||
|
|
||||||
// this should be optimized for tracers after prototyping
|
if (particleCount >= MaxParticles)
|
||||||
if (tracerPoints == null)
|
|
||||||
{
|
{
|
||||||
Vector2 particleEndPos = prefab.CalculateEndPosition(position, velocity);
|
for (int i = 0; i < particleCount; i++)
|
||||||
|
{
|
||||||
Vector2 minPos = new Vector2(Math.Min(position.X, particleEndPos.X), Math.Min(position.Y, particleEndPos.Y));
|
if (particles[i].Prefab.Priority < prefab.Priority)
|
||||||
Vector2 maxPos = new Vector2(Math.Max(position.X, particleEndPos.X), Math.Max(position.Y, particleEndPos.Y));
|
{
|
||||||
|
RemoveParticle(i);
|
||||||
Rectangle expandedViewRect = MathUtils.ExpandRect(cam.WorldView, MaxOutOfViewDist);
|
break;
|
||||||
|
}
|
||||||
if (minPos.X > expandedViewRect.Right || maxPos.X < expandedViewRect.X) { return null; }
|
}
|
||||||
if (minPos.Y > expandedViewRect.Y || maxPos.Y < expandedViewRect.Y - expandedViewRect.Height) { return null; }
|
if (particleCount >= MaxParticles) { return null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector2 particleEndPos = prefab.CalculateEndPosition(position, velocity);
|
||||||
|
|
||||||
|
Vector2 minPos = new Vector2(Math.Min(position.X, particleEndPos.X), Math.Min(position.Y, particleEndPos.Y));
|
||||||
|
Vector2 maxPos = new Vector2(Math.Max(position.X, particleEndPos.X), Math.Max(position.Y, particleEndPos.Y));
|
||||||
|
|
||||||
|
if (tracerPoints != null)
|
||||||
|
{
|
||||||
|
minPos = new Vector2(
|
||||||
|
Math.Min(Math.Min(minPos.X, tracerPoints.Item1.X), tracerPoints.Item2.X),
|
||||||
|
Math.Min(Math.Min(minPos.Y, tracerPoints.Item1.Y), tracerPoints.Item2.Y));
|
||||||
|
maxPos = new Vector2(
|
||||||
|
Math.Max(Math.Max(maxPos.X, tracerPoints.Item1.X), tracerPoints.Item2.X),
|
||||||
|
Math.Max(Math.Max(maxPos.Y, tracerPoints.Item1.Y), tracerPoints.Item2.Y));
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle expandedViewRect = MathUtils.ExpandRect(cam.WorldView, MaxOutOfViewDist);
|
||||||
|
|
||||||
|
if (minPos.X > expandedViewRect.Right || maxPos.X < expandedViewRect.X) { return null; }
|
||||||
|
if (minPos.Y > expandedViewRect.Y || maxPos.Y < expandedViewRect.Y - expandedViewRect.Height) { return null; }
|
||||||
|
|
||||||
if (particles[particleCount] == null) particles[particleCount] = new Particle();
|
if (particles[particleCount] == null) particles[particleCount] = new Particle();
|
||||||
|
|
||||||
particles[particleCount].Init(prefab, position, velocity, rotation, hullGuess, drawOnTop, collisionIgnoreTimer, tracerPoints: tracerPoints);
|
particles[particleCount].Init(prefab, position, velocity, rotation, hullGuess, drawOnTop, collisionIgnoreTimer, tracerPoints: tracerPoints);
|
||||||
@@ -165,7 +184,7 @@ namespace Barotrauma.Particles
|
|||||||
|
|
||||||
public ParticlePrefab FindPrefab(string prefabName)
|
public ParticlePrefab FindPrefab(string prefabName)
|
||||||
{
|
{
|
||||||
return Prefabs.Find(p => p.Identifier == prefabName);
|
return Prefabs.Find(p => p.Identifier.Equals(prefabName, StringComparison.OrdinalIgnoreCase));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RemoveParticle(int index)
|
private void RemoveParticle(int index)
|
||||||
|
|||||||
@@ -180,16 +180,13 @@ namespace Barotrauma.Particles
|
|||||||
[Editable, Serialize("1.0,1.0", false, description: "The maximum initial size of the particle.")]
|
[Editable, Serialize("1.0,1.0", false, description: "The maximum initial size of the particle.")]
|
||||||
public Vector2 StartSizeMax { get; private set; }
|
public Vector2 StartSizeMax { get; private set; }
|
||||||
|
|
||||||
[Editable]
|
[Editable, Serialize("0.0,0.0", false, description: "How much the size of the particle changes per second. The rate of growth for each particle is randomize between SizeChangeMin and SizeChangeMax.")]
|
||||||
[Serialize("0.0,0.0", false, description: "How much the size of the particle changes per second. The rate of growth for each particle is randomize between SizeChangeMin and SizeChangeMax.")]
|
|
||||||
public Vector2 SizeChangeMin { get; private set; }
|
public Vector2 SizeChangeMin { get; private set; }
|
||||||
|
|
||||||
[Editable]
|
[Editable, Serialize("0.0,0.0", false, description: "How much the size of the particle changes per second. The rate of growth for each particle is randomize between SizeChangeMin and SizeChangeMax.")]
|
||||||
[Serialize("0.0,0.0", false, description: "How much the size of the particle changes per second. The rate of growth for each particle is randomize between SizeChangeMin and SizeChangeMax.")]
|
|
||||||
public Vector2 SizeChangeMax { get; private set; }
|
public Vector2 SizeChangeMax { get; private set; }
|
||||||
|
|
||||||
[Editable]
|
[Editable, Serialize(0.0f, false, description: "How many seconds it takes for the particle to grow to it's initial size.")]
|
||||||
[Serialize(0.0f, false, description: "How many seconds it takes for the particle to grow to it's initial size.")]
|
|
||||||
public float GrowTime { get; private set; }
|
public float GrowTime { get; private set; }
|
||||||
|
|
||||||
//rendering -----------------------------------------
|
//rendering -----------------------------------------
|
||||||
@@ -215,6 +212,9 @@ namespace Barotrauma.Particles
|
|||||||
[Editable, Serialize(ParticleBlendState.AlphaBlend, false, description: "The type of blending to use when rendering the particle.")]
|
[Editable, Serialize(ParticleBlendState.AlphaBlend, false, description: "The type of blending to use when rendering the particle.")]
|
||||||
public ParticleBlendState BlendState { get; private set; }
|
public ParticleBlendState BlendState { get; private set; }
|
||||||
|
|
||||||
|
[Editable, Serialize(0, false, description: "Particles with a higher priority can replace lower-priority ones if the maximum number of active particles has been reached.")]
|
||||||
|
public int Priority { get; private set; }
|
||||||
|
|
||||||
//animation -----------------------------------------
|
//animation -----------------------------------------
|
||||||
|
|
||||||
[Editable(0.0f, float.MaxValue), Serialize(1.0f, false, description: "The duration of the particle's animation cycle (if it's animated).")]
|
[Editable(0.0f, float.MaxValue), Serialize(1.0f, false, description: "The duration of the particle's animation cycle (if it's animated).")]
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user