Unstable v0.1100.0.4 (November 11th 2020)
This commit is contained in:
@@ -330,7 +330,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
//how much to zoom out (zoom completely out when offset is 1000)
|
//how much to zoom out (zoom completely out when offset is 1000)
|
||||||
float zoomOutAmount = Math.Min(offset.Length() / 1000.0f, 1.0f);
|
float zoomOutAmount = GetZoomAmount(offset);
|
||||||
//zoom amount when resolution is not taken into account
|
//zoom amount when resolution is not taken into account
|
||||||
float unscaledZoom = MathHelper.Lerp(DefaultZoom, MinZoom, zoomOutAmount);
|
float unscaledZoom = MathHelper.Lerp(DefaultZoom, MinZoom, zoomOutAmount);
|
||||||
//zoom with resolution taken into account (zoom further out on smaller resolutions)
|
//zoom with resolution taken into account (zoom further out on smaller resolutions)
|
||||||
@@ -409,5 +409,15 @@ namespace Barotrauma
|
|||||||
//Vector2 screenCoords = Vector2.Transform(coords, transform);
|
//Vector2 screenCoords = Vector2.Transform(coords, transform);
|
||||||
return Vector2.Transform(coords, transform);
|
return Vector2.Transform(coords, transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private float GetZoomAmount(Vector2 offset)
|
||||||
|
{
|
||||||
|
return Math.Min(offset.Length() / 1000.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float GetZoomAmountFromPrevious()
|
||||||
|
{
|
||||||
|
return GetZoomAmount(previousOffset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -587,7 +587,16 @@ namespace Barotrauma
|
|||||||
PlaySound(CharacterSound.SoundType.Attack);
|
PlaySound(CharacterSound.SoundType.Attack);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
PlaySound(CharacterSound.SoundType.Idle);
|
var petBehavior = (AIController as EnemyAIController)?.PetBehavior;
|
||||||
|
if (petBehavior != null && petBehavior.Happiness < petBehavior.MaxHappiness * 0.25f)
|
||||||
|
{
|
||||||
|
PlaySound(CharacterSound.SoundType.Unhappy);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PlaySound(CharacterSound.SoundType.Idle);
|
||||||
|
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -801,7 +810,7 @@ namespace Barotrauma
|
|||||||
var iconStyle = GUI.Style.GetComponentStyle("CampaignInteractionBubble." + CampaignInteractionType);
|
var iconStyle = GUI.Style.GetComponentStyle("CampaignInteractionBubble." + CampaignInteractionType);
|
||||||
if (iconStyle != null)
|
if (iconStyle != null)
|
||||||
{
|
{
|
||||||
Vector2 headPos = AnimController.GetLimb(LimbType.Head)?.WorldPosition ?? WorldPosition + Vector2.UnitY * 100.0f;
|
Vector2 headPos = AnimController.GetLimb(LimbType.Head)?.body?.DrawPosition ?? DrawPosition + Vector2.UnitY * 100.0f;
|
||||||
Vector2 iconPos = headPos;
|
Vector2 iconPos = headPos;
|
||||||
iconPos.Y = -iconPos.Y;
|
iconPos.Y = -iconPos.Y;
|
||||||
nameColor = iconStyle.Color;
|
nameColor = iconStyle.Color;
|
||||||
@@ -826,7 +835,7 @@ namespace Barotrauma
|
|||||||
var iconStyle = GUI.Style.GetComponentStyle("PetIcon." + petStatus);
|
var iconStyle = GUI.Style.GetComponentStyle("PetIcon." + petStatus);
|
||||||
if (iconStyle != null)
|
if (iconStyle != null)
|
||||||
{
|
{
|
||||||
Vector2 headPos = AnimController.GetLimb(LimbType.Head)?.WorldPosition ?? WorldPosition + Vector2.UnitY * 100.0f;
|
Vector2 headPos = AnimController.GetLimb(LimbType.Head)?.body?.DrawPosition ?? DrawPosition + Vector2.UnitY * 100.0f;
|
||||||
Vector2 iconPos = headPos;
|
Vector2 iconPos = headPos;
|
||||||
iconPos.Y = -iconPos.Y;
|
iconPos.Y = -iconPos.Y;
|
||||||
var icon = iconStyle.Sprites[GUIComponent.ComponentState.None].First();
|
var icon = iconStyle.Sprites[GUIComponent.ComponentState.None].First();
|
||||||
@@ -877,11 +886,12 @@ 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)
|
public void PlaySound(CharacterSound.SoundType soundType, float soundIntervalFactor = 1.0f)
|
||||||
{
|
{
|
||||||
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; }
|
||||||
matchingSounds.Clear();
|
matchingSounds.Clear();
|
||||||
foreach (var s in sounds)
|
foreach (var s in sounds)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,15 +11,15 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
class CharacterHUD
|
class CharacterHUD
|
||||||
{
|
{
|
||||||
private static Dictionary<ISpatialEntity, int> orderIndicatorCount = new Dictionary<ISpatialEntity, int>();
|
private static readonly Dictionary<ISpatialEntity, int> orderIndicatorCount = new Dictionary<ISpatialEntity, int>();
|
||||||
const float ItemOverlayDelay = 1.0f;
|
const float ItemOverlayDelay = 1.0f;
|
||||||
private static Item focusedItem;
|
private static Item focusedItem;
|
||||||
private static float focusedItemOverlayTimer;
|
private static float focusedItemOverlayTimer;
|
||||||
|
|
||||||
private static List<Item> brokenItems = new List<Item>();
|
private static readonly List<Item> brokenItems = new List<Item>();
|
||||||
private static float brokenItemsCheckTimer;
|
private static float brokenItemsCheckTimer;
|
||||||
|
|
||||||
private static Dictionary<string, string> cachedHudTexts = new Dictionary<string, string>();
|
private static readonly Dictionary<string, string> cachedHudTexts = new Dictionary<string, string>();
|
||||||
|
|
||||||
private static GUIFrame hudFrame;
|
private static GUIFrame hudFrame;
|
||||||
public static GUIFrame HUDFrame
|
public static GUIFrame HUDFrame
|
||||||
@@ -126,6 +126,11 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
character.Inventory.Update(deltaTime, cam);
|
character.Inventory.Update(deltaTime, cam);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
character.Inventory.ClearSubInventories();
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < character.Inventory.Items.Length - 1; i++)
|
for (int i = 0; i < character.Inventory.Items.Length - 1; i++)
|
||||||
{
|
{
|
||||||
var item = character.Inventory.Items[i];
|
var item = character.Inventory.Items[i];
|
||||||
@@ -199,9 +204,18 @@ namespace Barotrauma
|
|||||||
if (GameMain.GameSession?.CrewManager != null)
|
if (GameMain.GameSession?.CrewManager != null)
|
||||||
{
|
{
|
||||||
orderIndicatorCount.Clear();
|
orderIndicatorCount.Clear();
|
||||||
foreach (Pair<Order, float> timedOrder in GameMain.GameSession.CrewManager.ActiveOrders)
|
foreach (Pair<Order, float?> activeOrder in GameMain.GameSession.CrewManager.ActiveOrders)
|
||||||
{
|
{
|
||||||
DrawOrderIndicator(spriteBatch, cam, character, timedOrder.First, MathHelper.Clamp(timedOrder.Second / 10.0f, 0.2f, 1.0f));
|
if (activeOrder.Second.HasValue)
|
||||||
|
{
|
||||||
|
DrawOrderIndicator(spriteBatch, cam, character, activeOrder.First, iconAlpha: MathHelper.Clamp(activeOrder.Second.Value / 10.0f, 0.2f, 1.0f));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float iconAlpha = GetDistanceBasedIconAlpha(activeOrder.First.TargetSpatialEntity, maxDistance: 350.0f);
|
||||||
|
if (iconAlpha <= 0.0f) { continue; }
|
||||||
|
DrawOrderIndicator(spriteBatch, cam, character, activeOrder.First, iconAlpha: iconAlpha, createOffset: false, scaleMultiplier: 0.5f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (character.CurrentOrder != null)
|
if (character.CurrentOrder != null)
|
||||||
@@ -218,14 +232,18 @@ namespace Barotrauma
|
|||||||
foreach (Item brokenItem in brokenItems)
|
foreach (Item brokenItem in brokenItems)
|
||||||
{
|
{
|
||||||
if (brokenItem.NonInteractable) { continue; }
|
if (brokenItem.NonInteractable) { continue; }
|
||||||
float dist = Vector2.Distance(character.WorldPosition, brokenItem.WorldPosition);
|
float alpha = GetDistanceBasedIconAlpha(brokenItem);
|
||||||
Vector2 drawPos = brokenItem.DrawPosition;
|
|
||||||
float alpha = Math.Min((1000.0f - dist) / 1000.0f * 2.0f, 1.0f);
|
|
||||||
if (alpha <= 0.0f) continue;
|
if (alpha <= 0.0f) continue;
|
||||||
GUI.DrawIndicator(spriteBatch, drawPos, cam, 100.0f, GUI.BrokenIcon,
|
GUI.DrawIndicator(spriteBatch, brokenItem.DrawPosition, cam, 100.0f, GUI.BrokenIcon,
|
||||||
Color.Lerp(GUI.Style.Red, GUI.Style.Orange * 0.5f, brokenItem.Condition / brokenItem.MaxCondition) * alpha);
|
Color.Lerp(GUI.Style.Red, GUI.Style.Orange * 0.5f, brokenItem.Condition / brokenItem.MaxCondition) * alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float GetDistanceBasedIconAlpha(ISpatialEntity target, float maxDistance = 1000.0f)
|
||||||
|
{
|
||||||
|
float dist = Vector2.Distance(character.WorldPosition, target.WorldPosition);
|
||||||
|
return Math.Min((maxDistance - dist) / maxDistance * 2.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
if (!character.IsIncapacitated && character.Stun <= 0.0f && !IsCampaignInterfaceOpen && (!character.IsKeyDown(InputType.Aim) || character.SelectedItems.Any(it => it?.GetComponent<Sprayer>() == null)))
|
if (!character.IsIncapacitated && character.Stun <= 0.0f && !IsCampaignInterfaceOpen && (!character.IsKeyDown(InputType.Aim) || character.SelectedItems.Any(it => it?.GetComponent<Sprayer>() == null)))
|
||||||
{
|
{
|
||||||
if (character.FocusedCharacter != null && character.FocusedCharacter.CanBeSelected)
|
if (character.FocusedCharacter != null && character.FocusedCharacter.CanBeSelected)
|
||||||
@@ -362,8 +380,8 @@ namespace Barotrauma
|
|||||||
(int)(HUDLayoutSettings.BottomRightInfoArea.X + HUDLayoutSettings.BottomRightInfoArea.Width * 0.05f),
|
(int)(HUDLayoutSettings.BottomRightInfoArea.X + HUDLayoutSettings.BottomRightInfoArea.Width * 0.05f),
|
||||||
(int)(HUDLayoutSettings.BottomRightInfoArea.Y + HUDLayoutSettings.BottomRightInfoArea.Height * 0.1f),
|
(int)(HUDLayoutSettings.BottomRightInfoArea.Y + HUDLayoutSettings.BottomRightInfoArea.Height * 0.1f),
|
||||||
(int)(HUDLayoutSettings.BottomRightInfoArea.Width / 2),
|
(int)(HUDLayoutSettings.BottomRightInfoArea.Width / 2),
|
||||||
(int)(HUDLayoutSettings.BottomRightInfoArea.Height * 0.7f)));
|
(int)(HUDLayoutSettings.BottomRightInfoArea.Height * 0.7f)), character.Info.IsDisguisedAsAnother);
|
||||||
character.Info.DrawPortrait(spriteBatch, HUDLayoutSettings.PortraitArea.Location.ToVector2(), new Vector2(-12 * GUI.Scale, 4 * GUI.Scale), targetWidth: HUDLayoutSettings.PortraitArea.Width, true);
|
character.Info.DrawPortrait(spriteBatch, HUDLayoutSettings.PortraitArea.Location.ToVector2(), new Vector2(-12 * GUI.Scale, 4 * GUI.Scale), targetWidth: HUDLayoutSettings.PortraitArea.Width, true, character.Info.IsDisguisedAsAnother);
|
||||||
}
|
}
|
||||||
mouseOnPortrait = HUDLayoutSettings.BottomRightInfoArea.Contains(PlayerInput.MousePosition) && !character.ShouldLockHud();
|
mouseOnPortrait = HUDLayoutSettings.BottomRightInfoArea.Contains(PlayerInput.MousePosition) && !character.ShouldLockHud();
|
||||||
if (mouseOnPortrait)
|
if (mouseOnPortrait)
|
||||||
@@ -426,7 +444,7 @@ namespace Barotrauma
|
|||||||
Vector2 startPos = character.DrawPosition + (character.FocusedCharacter.DrawPosition - character.DrawPosition) * 0.7f;
|
Vector2 startPos = character.DrawPosition + (character.FocusedCharacter.DrawPosition - character.DrawPosition) * 0.7f;
|
||||||
startPos = cam.WorldToScreen(startPos);
|
startPos = cam.WorldToScreen(startPos);
|
||||||
|
|
||||||
string focusName = character.FocusedCharacter.DisplayName;
|
string focusName = character.FocusedCharacter.Info == null ? character.FocusedCharacter.DisplayName : character.FocusedCharacter.Info.DisplayName;
|
||||||
Vector2 textPos = startPos;
|
Vector2 textPos = startPos;
|
||||||
Vector2 textSize = GUI.Font.MeasureString(focusName);
|
Vector2 textSize = GUI.Font.MeasureString(focusName);
|
||||||
Vector2 largeTextSize = GUI.SubHeadingFont.MeasureString(focusName);
|
Vector2 largeTextSize = GUI.SubHeadingFont.MeasureString(focusName);
|
||||||
@@ -475,19 +493,12 @@ namespace Barotrauma
|
|||||||
return character.ShouldLockHud();
|
return character.ShouldLockHud();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DrawOrderIndicator(SpriteBatch spriteBatch, Camera cam, Character character, Order order, float iconAlpha = 1.0f)
|
private static void DrawOrderIndicator(SpriteBatch spriteBatch, Camera cam, Character character, Order order, float iconAlpha = 1.0f, bool createOffset = true, float scaleMultiplier = 1.0f)
|
||||||
{
|
{
|
||||||
if (order?.SymbolSprite == null) { return; }
|
if (order?.SymbolSprite == null) { return; }
|
||||||
|
if (order.IsReport && order.OrderGiver != character && !order.HasAppropriateJob(character)) { return; }
|
||||||
|
|
||||||
if (order.TargetAllCharacters)
|
ISpatialEntity target = order.ConnectedController?.Item ?? order.TargetSpatialEntity;
|
||||||
{
|
|
||||||
if (order.OrderGiver != character && !order.HasAppropriateJob(character))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ISpatialEntity target = order.ConnectedController != null ? order.ConnectedController.Item : order.TargetSpatialEntity;
|
|
||||||
if (target == null) { return; }
|
if (target == null) { return; }
|
||||||
|
|
||||||
//don't show the indicator if far away and not inside the same sub
|
//don't show the indicator if far away and not inside the same sub
|
||||||
@@ -503,7 +514,7 @@ namespace Barotrauma
|
|||||||
Vector2 drawPos = target is Entity ? (target as Entity).DrawPosition :
|
Vector2 drawPos = target is Entity ? (target as Entity).DrawPosition :
|
||||||
target.Submarine == null ? target.Position : target.Position + target.Submarine.DrawPosition;
|
target.Submarine == null ? target.Position : target.Position + target.Submarine.DrawPosition;
|
||||||
drawPos += Vector2.UnitX * order.SymbolSprite.size.X * 1.5f * orderIndicatorCount[target];
|
drawPos += Vector2.UnitX * order.SymbolSprite.size.X * 1.5f * orderIndicatorCount[target];
|
||||||
GUI.DrawIndicator(spriteBatch, drawPos, cam, 100.0f, order.SymbolSprite, order.Color * iconAlpha);
|
GUI.DrawIndicator(spriteBatch, drawPos, cam, 100.0f, order.SymbolSprite, order.Color * iconAlpha, createOffset: createOffset, scaleMultiplier: scaleMultiplier);
|
||||||
|
|
||||||
orderIndicatorCount[target] = orderIndicatorCount[target] + 1;
|
orderIndicatorCount[target] = orderIndicatorCount[target] + 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ using System.Collections.Generic;
|
|||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
using System.IO;
|
||||||
|
using Barotrauma.Items.Components;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -15,6 +17,12 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public bool LastControlled;
|
public bool LastControlled;
|
||||||
|
|
||||||
|
private Sprite disguisedPortrait;
|
||||||
|
private List<WearableSprite> disguisedAttachmentSprites;
|
||||||
|
private Vector2? disguisedSheetIndex;
|
||||||
|
private Sprite disguisedJobIcon;
|
||||||
|
private Color disguisedJobColor;
|
||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
{
|
||||||
infoAreaPortraitBG = GUI.Style.GetComponentStyle("InfoAreaPortraitBG")?.GetDefaultSprite();
|
infoAreaPortraitBG = GUI.Style.GetComponentStyle("InfoAreaPortraitBG")?.GetDefaultSprite();
|
||||||
@@ -175,6 +183,195 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void GetDisguisedSprites(IdCard idCard)
|
||||||
|
{
|
||||||
|
if (idCard.StoredJobPrefab == null || idCard.StoredPortrait == null)
|
||||||
|
{
|
||||||
|
string[] readTags = idCard.Item.Tags.Split(',');
|
||||||
|
|
||||||
|
if (idCard.StoredJobPrefab == null)
|
||||||
|
{
|
||||||
|
string jobIdTag = readTags.First(s => s.StartsWith("jobid:"));
|
||||||
|
|
||||||
|
if (jobIdTag != string.Empty && jobIdTag.Length > 6)
|
||||||
|
{
|
||||||
|
string jobId = jobIdTag.Substring(6);
|
||||||
|
if (jobId != string.Empty)
|
||||||
|
{
|
||||||
|
idCard.StoredJobPrefab = JobPrefab.Get(jobId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idCard.StoredPortrait == null)
|
||||||
|
{
|
||||||
|
string disguisedGender = string.Empty;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
disguisedJobIcon = idCard.StoredJobPrefab.Icon;
|
||||||
|
disguisedJobColor = idCard.StoredJobPrefab.UIColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
disguisedPortrait = idCard.StoredPortrait;
|
||||||
|
disguisedSheetIndex = idCard.StoredSheetIndex;
|
||||||
|
disguisedAttachmentSprites = idCard.StoredAttachments;
|
||||||
|
}
|
||||||
|
|
||||||
partial void LoadAttachmentSprites(bool omitJob)
|
partial void LoadAttachmentSprites(bool omitJob)
|
||||||
{
|
{
|
||||||
if (attachmentSprites == null)
|
if (attachmentSprites == null)
|
||||||
@@ -219,23 +416,42 @@ namespace Barotrauma
|
|||||||
HUDLayoutSettings.BottomRightInfoArea.Height / (float)infoAreaPortraitBG.SourceRect.Height));
|
HUDLayoutSettings.BottomRightInfoArea.Height / (float)infoAreaPortraitBG.SourceRect.Height));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DrawPortrait(SpriteBatch spriteBatch, Vector2 screenPos, Vector2 offset, float targetWidth, bool flip = false)
|
public void DrawPortrait(SpriteBatch spriteBatch, Vector2 screenPos, Vector2 offset, float targetWidth, bool flip = false, bool evaluateDisguise = false)
|
||||||
{
|
{
|
||||||
if (Portrait != null)
|
if (evaluateDisguise && IsDisguised) return;
|
||||||
|
|
||||||
|
Vector2? sheetIndex;
|
||||||
|
Sprite portraitToDraw;
|
||||||
|
List<WearableSprite> attachmentsToDraw;
|
||||||
|
|
||||||
|
if (!IsDisguisedAsAnother || !evaluateDisguise)
|
||||||
|
{
|
||||||
|
sheetIndex = Head.SheetIndex;
|
||||||
|
portraitToDraw = Portrait;
|
||||||
|
attachmentsToDraw = AttachmentSprites;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sheetIndex = disguisedSheetIndex;
|
||||||
|
portraitToDraw = disguisedPortrait;
|
||||||
|
attachmentsToDraw = disguisedAttachmentSprites;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (portraitToDraw != null)
|
||||||
{
|
{
|
||||||
// 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 (Head.SheetIndex.HasValue)
|
if (sheetIndex.HasValue)
|
||||||
{
|
{
|
||||||
Portrait.SourceRect = new Rectangle(CalculateOffset(Portrait, Head.SheetIndex.Value.ToPoint()), Portrait.SourceRect.Size);
|
portraitToDraw.SourceRect = new Rectangle(CalculateOffset(portraitToDraw, sheetIndex.Value.ToPoint()), portraitToDraw.SourceRect.Size);
|
||||||
}
|
}
|
||||||
Portrait.Draw(spriteBatch, screenPos + offset, Color.White, Portrait.Origin, scale: scale, spriteEffect: flip ? SpriteEffects.FlipHorizontally : SpriteEffects.None);
|
portraitToDraw.Draw(spriteBatch, screenPos + offset, Color.White, portraitToDraw.Origin, scale: scale, spriteEffect: flip ? SpriteEffects.FlipHorizontally : SpriteEffects.None);
|
||||||
if (AttachmentSprites != null)
|
if (attachmentsToDraw != null)
|
||||||
{
|
{
|
||||||
float depthStep = 0.000001f;
|
float depthStep = 0.000001f;
|
||||||
foreach (var attachment in AttachmentSprites)
|
foreach (var attachment in attachmentsToDraw)
|
||||||
{
|
{
|
||||||
DrawAttachmentSprite(spriteBatch, attachment, Portrait, screenPos + offset, scale, depthStep, flip ? SpriteEffects.FlipHorizontally : SpriteEffects.None);
|
DrawAttachmentSprite(spriteBatch, attachment, portraitToDraw, sheetIndex, screenPos + offset, scale, depthStep, flip ? SpriteEffects.FlipHorizontally : SpriteEffects.None);
|
||||||
depthStep += depthStep;
|
depthStep += depthStep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -258,30 +474,34 @@ namespace Barotrauma
|
|||||||
float depthStep = 0.000001f;
|
float depthStep = 0.000001f;
|
||||||
foreach (var attachment in AttachmentSprites)
|
foreach (var attachment in AttachmentSprites)
|
||||||
{
|
{
|
||||||
DrawAttachmentSprite(spriteBatch, attachment, headSprite, screenPos, scale, depthStep);
|
DrawAttachmentSprite(spriteBatch, attachment, headSprite, Head.SheetIndex, screenPos, scale, depthStep);
|
||||||
depthStep += depthStep;
|
depthStep += depthStep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DrawJobIcon(SpriteBatch spriteBatch, Vector2 pos, float scale = 1.0f)
|
public void DrawJobIcon(SpriteBatch spriteBatch, Vector2 pos, float scale = 1.0f, bool evaluateDisguise = false)
|
||||||
{
|
{
|
||||||
var icon = Job?.Prefab?.Icon;
|
if (evaluateDisguise && IsDisguised) return;
|
||||||
|
var icon = !IsDisguisedAsAnother || !evaluateDisguise ? Job?.Prefab?.Icon : disguisedJobIcon;
|
||||||
if (icon == null) { return; }
|
if (icon == null) { return; }
|
||||||
icon.Draw(spriteBatch, pos, Job.Prefab.UIColor, scale: scale);
|
Color iconColor = !IsDisguisedAsAnother || !evaluateDisguise ? Job.Prefab.UIColor : disguisedJobColor;
|
||||||
}
|
|
||||||
public void DrawJobIcon(SpriteBatch spriteBatch, Rectangle area)
|
icon.Draw(spriteBatch, pos, iconColor, scale: scale);
|
||||||
{
|
|
||||||
var icon = Job?.Prefab?.Icon;
|
|
||||||
if (icon == null) { return; }
|
|
||||||
icon.Draw(spriteBatch,
|
|
||||||
area.Center.ToVector2(),
|
|
||||||
Job.Prefab.UIColor,
|
|
||||||
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 drawPos, float scale, float depthStep, SpriteEffects spriteEffects = SpriteEffects.None)
|
public void DrawJobIcon(SpriteBatch spriteBatch, Rectangle area, 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, 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)
|
||||||
{
|
{
|
||||||
if (attachment.InheritSourceRect)
|
if (attachment.InheritSourceRect)
|
||||||
{
|
{
|
||||||
@@ -289,9 +509,9 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
attachment.Sprite.SourceRect = new Rectangle(CalculateOffset(head, attachment.SheetIndex.Value), head.SourceRect.Size);
|
attachment.Sprite.SourceRect = new Rectangle(CalculateOffset(head, attachment.SheetIndex.Value), head.SourceRect.Size);
|
||||||
}
|
}
|
||||||
else if (Head.SheetIndex.HasValue)
|
else if (sheetIndex.HasValue)
|
||||||
{
|
{
|
||||||
attachment.Sprite.SourceRect = new Rectangle(CalculateOffset(head, Head.SheetIndex.Value.ToPoint()), head.SourceRect.Size);
|
attachment.Sprite.SourceRect = new Rectangle(CalculateOffset(head, sheetIndex.Value.ToPoint()), head.SourceRect.Size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -84,6 +84,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
newMem.interact = FocusedCharacter.ID;
|
newMem.interact = FocusedCharacter.ID;
|
||||||
}
|
}
|
||||||
|
else if (newMem.states.HasFlag(InputNetFlags.Use) && (FocusedCharacter?.IsPet ?? false))
|
||||||
|
{
|
||||||
|
newMem.interact = FocusedCharacter.ID;
|
||||||
|
}
|
||||||
else if (focusedItem != null && !CharacterInventory.DraggingItemToWorld &&
|
else if (focusedItem != null && !CharacterInventory.DraggingItemToWorld &&
|
||||||
!newMem.states.HasFlag(InputNetFlags.Grab) && !newMem.states.HasFlag(InputNetFlags.Health))
|
!newMem.states.HasFlag(InputNetFlags.Grab) && !newMem.states.HasFlag(InputNetFlags.Health))
|
||||||
{
|
{
|
||||||
@@ -254,6 +258,7 @@ namespace Barotrauma
|
|||||||
if (readStatus)
|
if (readStatus)
|
||||||
{
|
{
|
||||||
ReadStatus(msg);
|
ReadStatus(msg);
|
||||||
|
(AIController as EnemyAIController)?.PetBehavior?.ClientRead(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.ReadPadBits();
|
msg.ReadPadBits();
|
||||||
@@ -411,8 +416,7 @@ namespace Barotrauma
|
|||||||
Character character = null;
|
Character character = null;
|
||||||
if (noInfo)
|
if (noInfo)
|
||||||
{
|
{
|
||||||
character = Create(speciesName, position, seed, null, false);
|
character = Create(speciesName, position, seed, characterInfo: null, id: id, isRemotePlayer: false);
|
||||||
character.ID = id;
|
|
||||||
bool containsStatusData = inc.ReadBoolean();
|
bool containsStatusData = inc.ReadBoolean();
|
||||||
if (containsStatusData)
|
if (containsStatusData)
|
||||||
{
|
{
|
||||||
@@ -429,8 +433,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
CharacterInfo info = CharacterInfo.ClientRead(infoSpeciesName, inc);
|
CharacterInfo info = CharacterInfo.ClientRead(infoSpeciesName, inc);
|
||||||
|
|
||||||
character = Create(speciesName, position, seed, info, ownerId > 0 && GameMain.Client.ID != ownerId, hasAi);
|
character = Create(speciesName, position, seed, characterInfo: info, id: id, isRemotePlayer: ownerId > 0 && GameMain.Client.ID != ownerId, hasAi: hasAi);
|
||||||
character.ID = id;
|
|
||||||
character.TeamID = (TeamType)teamID;
|
character.TeamID = (TeamType)teamID;
|
||||||
character.CampaignInteractionType = (CampaignMode.InteractionType)inc.ReadByte();
|
character.CampaignInteractionType = (CampaignMode.InteractionType)inc.ReadByte();
|
||||||
if (character.CampaignInteractionType != CampaignMode.InteractionType.None)
|
if (character.CampaignInteractionType != CampaignMode.InteractionType.None)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
public enum SoundType
|
public enum SoundType
|
||||||
{
|
{
|
||||||
Idle, Attack, Die, Damage
|
Idle, Attack, Die, Damage, Happy, Unhappy
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly RoundSound roundSound;
|
private readonly RoundSound roundSound;
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private GUIFrame healthWindow;
|
private GUIFrame healthWindow;
|
||||||
|
|
||||||
private GUIComponent deadIndicator;
|
private GUITextBlock deadIndicator;
|
||||||
|
|
||||||
private GUIComponent lowSkillIndicator;
|
private GUIComponent lowSkillIndicator;
|
||||||
|
|
||||||
@@ -225,7 +225,16 @@ namespace Barotrauma
|
|||||||
Character.Controlled.ResetInteract = true;
|
Character.Controlled.ResetInteract = true;
|
||||||
if (openHealthWindow != null)
|
if (openHealthWindow != null)
|
||||||
{
|
{
|
||||||
openHealthWindow.characterName.Text = value.Character.Name;
|
if (value.Character.Info == null || value.Character == Character.Controlled || Character.Controlled.HasEquippedItem("healthscanner"))
|
||||||
|
{
|
||||||
|
openHealthWindow.characterName.Text = value.Character.Name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
openHealthWindow.characterName.Text = value.Character.Info.DisplayName;
|
||||||
|
value.Character.Info.CheckDisguiseStatus(false);
|
||||||
|
}
|
||||||
|
|
||||||
if (Character.Controlled.SelectedConstruction != null && Character.Controlled.SelectedConstruction.GetComponent<Ladder>() == null)
|
if (Character.Controlled.SelectedConstruction != null && Character.Controlled.SelectedConstruction.GetComponent<Ladder>() == null)
|
||||||
{
|
{
|
||||||
Character.Controlled.SelectedConstruction = null;
|
Character.Controlled.SelectedConstruction = null;
|
||||||
@@ -322,11 +331,19 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
deadIndicator = new GUITextBlock(new RectTransform(new Vector2(0.9f, 0.1f), limbSelection.RectTransform, Anchor.Center),
|
deadIndicator = new GUITextBlock(new RectTransform(new Vector2(0.9f, 0.1f), limbSelection.RectTransform, Anchor.Center),
|
||||||
text: TextManager.Get("Deceased"), font: GUI.LargeFont, textAlignment: Alignment.Center, wrap: true, style: "GUIToolTip")
|
text: TextManager.Get("Deceased"), font: GUI.LargeFont, textAlignment: Alignment.Center, style: "GUIToolTip")
|
||||||
{
|
{
|
||||||
Visible = false,
|
Visible = false,
|
||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
|
if (deadIndicator.Text.Contains(' '))
|
||||||
|
{
|
||||||
|
deadIndicator.Wrap = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
deadIndicator.AutoScaleHorizontal = true;
|
||||||
|
}
|
||||||
|
|
||||||
var rightSide = new GUIFrame(new RectTransform(new Vector2(0.4f, 1.0f), paddedHealthWindow.RectTransform), style: null);
|
var rightSide = new GUIFrame(new RectTransform(new Vector2(0.4f, 1.0f), paddedHealthWindow.RectTransform), style: null);
|
||||||
|
|
||||||
@@ -397,15 +414,17 @@ namespace Barotrauma
|
|||||||
CanBeFocused = true
|
CanBeFocused = true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
textLayout.RectTransform.RelativeOffset = new Vector2(0, 0.025f);
|
||||||
|
|
||||||
var nameContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.2f), textLayout.RectTransform) { MinSize = new Point(0, 20) }, isHorizontal: true)
|
var nameContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.2f), textLayout.RectTransform) { MinSize = new Point(0, 20) }, isHorizontal: true)
|
||||||
{
|
{
|
||||||
Stretch = true
|
Stretch = true
|
||||||
};
|
};
|
||||||
|
|
||||||
new GUICustomComponent(new RectTransform(new Vector2(0.2f, 1.0f), nameContainer.RectTransform),
|
new GUICustomComponent(new RectTransform(new Vector2(0.2f, 1.0f), nameContainer.RectTransform, Anchor.CenterLeft),
|
||||||
onDraw: (spriteBatch, component) =>
|
onDraw: (spriteBatch, component) =>
|
||||||
{
|
{
|
||||||
character.Info.DrawPortrait(spriteBatch, new Vector2(component.Rect.X, component.Rect.Center.Y - component.Rect.Width / 2), Vector2.Zero, component.Rect.Width);
|
character.Info.DrawPortrait(spriteBatch, new Vector2(component.Rect.X, component.Rect.Center.Y - component.Rect.Width / 2), Vector2.Zero, component.Rect.Width, false, openHealthWindow?.Character != Character.Controlled);
|
||||||
});
|
});
|
||||||
characterName = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), nameContainer.RectTransform), "", textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont)
|
characterName = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), nameContainer.RectTransform), "", textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont)
|
||||||
{
|
{
|
||||||
@@ -414,7 +433,7 @@ namespace Barotrauma
|
|||||||
new GUICustomComponent(new RectTransform(new Vector2(0.2f, 1.0f), nameContainer.RectTransform),
|
new GUICustomComponent(new RectTransform(new Vector2(0.2f, 1.0f), nameContainer.RectTransform),
|
||||||
onDraw: (spriteBatch, component) =>
|
onDraw: (spriteBatch, component) =>
|
||||||
{
|
{
|
||||||
character.Info.DrawJobIcon(spriteBatch, component.Rect);
|
character.Info.DrawJobIcon(spriteBatch, component.Rect, openHealthWindow?.Character != Character.Controlled);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -943,6 +962,28 @@ namespace Barotrauma
|
|||||||
|
|
||||||
SuicideButton.Visible = Character == Character.Controlled && !Character.IsDead && Character.IsIncapacitated;
|
SuicideButton.Visible = Character == Character.Controlled && !Character.IsDead && Character.IsIncapacitated;
|
||||||
|
|
||||||
|
if (GameMain.GameSession?.Campaign is { } campaign)
|
||||||
|
{
|
||||||
|
RectTransform endRoundButton = campaign?.EndRoundButton?.RectTransform;
|
||||||
|
RectTransform readyCheckButton = campaign?.ReadyCheckButton?.RectTransform;
|
||||||
|
if (endRoundButton != null)
|
||||||
|
{
|
||||||
|
if (SuicideButton.Visible)
|
||||||
|
{
|
||||||
|
Point offset = new Point(0, SuicideButton.Rect.Height);
|
||||||
|
endRoundButton.ScreenSpaceOffset = offset;
|
||||||
|
}
|
||||||
|
else if (endRoundButton.ScreenSpaceOffset != Point.Zero)
|
||||||
|
{
|
||||||
|
endRoundButton.ScreenSpaceOffset = Point.Zero;
|
||||||
|
}
|
||||||
|
if (readyCheckButton != null)
|
||||||
|
{
|
||||||
|
readyCheckButton.ScreenSpaceOffset = endRoundButton.ScreenSpaceOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cprButton.Visible =
|
cprButton.Visible =
|
||||||
Character == Character.Controlled?.SelectedCharacter
|
Character == Character.Controlled?.SelectedCharacter
|
||||||
&& (Character.IsUnconscious || Character.Stun > 0.0f)
|
&& (Character.IsUnconscious || Character.Stun > 0.0f)
|
||||||
|
|||||||
@@ -328,8 +328,7 @@ namespace Barotrauma
|
|||||||
deformation = ragdoll.Limbs
|
deformation = ragdoll.Limbs
|
||||||
.Where(l => l != null)
|
.Where(l => l != null)
|
||||||
.SelectMany(l => l.Deformations)
|
.SelectMany(l => l.Deformations)
|
||||||
.Where(d => d.TypeName == typeName && d.Sync == sync)
|
.FirstOrDefault(d => d.TypeName == typeName && d.Sync == sync);
|
||||||
.FirstOrDefault();
|
|
||||||
}
|
}
|
||||||
if (deformation == null)
|
if (deformation == null)
|
||||||
{
|
{
|
||||||
@@ -971,11 +970,11 @@ namespace Barotrauma
|
|||||||
XElement element;
|
XElement element;
|
||||||
if (random)
|
if (random)
|
||||||
{
|
{
|
||||||
element = info.FilterByTypeAndHeadID(character.Info.FilterElementsByGenderAndRace(character.Info.Wearables), type)?.GetRandom(Rand.RandSync.ClientOnly);
|
element = info.FilterByTypeAndHeadID(info.FilterElementsByGenderAndRace(info.Wearables, info.Gender, info.Race), type, info.Head.HeadSpriteId)?.GetRandom(Rand.RandSync.ClientOnly);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
element = info.FilterByTypeAndHeadID(character.Info.FilterElementsByGenderAndRace(character.Info.Wearables), type)?.FirstOrDefault();
|
element = info.FilterByTypeAndHeadID(info.FilterElementsByGenderAndRace(info.Wearables, info.Gender, info.Race), type, info.Head.HeadSpriteId)?.FirstOrDefault();
|
||||||
}
|
}
|
||||||
if (element != null)
|
if (element != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -491,7 +491,11 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
SteamManager.NetworkingDebugLog = !SteamManager.NetworkingDebugLog;
|
SteamManager.NetworkingDebugLog = !SteamManager.NetworkingDebugLog;
|
||||||
SteamManager.SetSteamworksNetworkingDebugLog(SteamManager.NetworkingDebugLog);
|
SteamManager.SetSteamworksNetworkingDebugLog(SteamManager.NetworkingDebugLog);
|
||||||
|
}));
|
||||||
|
|
||||||
|
commands.Add(new Command("readycheck", "Commence a ready check in multiplayer.", (string[] args) =>
|
||||||
|
{
|
||||||
|
NewMessage("Ready checks can only be commenced in multiplayer.", Color.Red);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
AssignRelayToServer("kick", false);
|
AssignRelayToServer("kick", false);
|
||||||
@@ -527,6 +531,7 @@ namespace Barotrauma
|
|||||||
AssignRelayToServer("traitorlist", true);
|
AssignRelayToServer("traitorlist", true);
|
||||||
AssignRelayToServer("money", true);
|
AssignRelayToServer("money", true);
|
||||||
AssignRelayToServer("setskill", true);
|
AssignRelayToServer("setskill", true);
|
||||||
|
AssignRelayToServer("readycheck", true);
|
||||||
|
|
||||||
AssignOnExecute("control", (string[] args) =>
|
AssignOnExecute("control", (string[] args) =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using Barotrauma.Networking;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
partial class BeaconMission : Mission
|
||||||
|
{
|
||||||
|
public override void ClientReadInitial(IReadMessage msg)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
partial class CombatMission
|
partial class CombatMission : Mission
|
||||||
{
|
{
|
||||||
public override string Description
|
public override string Description
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
using Barotrauma.Extensions;
|
||||||
|
using Barotrauma.Items.Components;
|
||||||
|
using Barotrauma.Networking;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
partial class MineralMission : Mission
|
||||||
|
{
|
||||||
|
public override void ClientReadInitial(IReadMessage msg)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < ResourceClusters.Count; i++)
|
||||||
|
{
|
||||||
|
var amount = msg.ReadByte();
|
||||||
|
var rotation = msg.ReadSingle();
|
||||||
|
for (int j = 0; j < amount; j++)
|
||||||
|
{
|
||||||
|
var item = Item.ReadSpawnData(msg);
|
||||||
|
if (item.GetComponent<Holdable>() is Holdable h)
|
||||||
|
{
|
||||||
|
h.AttachToWall();
|
||||||
|
item.Rotation = rotation;
|
||||||
|
}
|
||||||
|
if (SpawnedResources.TryGetValue(item.Prefab.Identifier, out var resources))
|
||||||
|
{
|
||||||
|
resources.Add(item);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SpawnedResources.Add(item.Prefab.Identifier, new List<Item>() { item });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CalculateMissionClusterPositions();
|
||||||
|
|
||||||
|
for(int i = 0; i < ResourceClusters.Count; i++)
|
||||||
|
{
|
||||||
|
var identifier = msg.ReadString();
|
||||||
|
var count = msg.ReadByte();
|
||||||
|
var resources = new Item[count];
|
||||||
|
for (int j = 0; j < count; j++)
|
||||||
|
{
|
||||||
|
var id = msg.ReadUInt16();
|
||||||
|
var entity = Entity.FindEntityByID(id);
|
||||||
|
if (!(entity is Item item)) { continue; }
|
||||||
|
resources[j] = item;
|
||||||
|
}
|
||||||
|
RelevantLevelResources.Add(identifier, resources);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ using System.Collections.Generic;
|
|||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
partial class Mission
|
abstract partial class Mission
|
||||||
{
|
{
|
||||||
partial void ShowMessageProjSpecific(int missionState)
|
partial void ShowMessageProjSpecific(int missionState)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using System;
|
|||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
partial class MissionMode : GameMode
|
abstract partial class MissionMode : GameMode
|
||||||
{
|
{
|
||||||
public override void ShowStartMessage()
|
public override void ShowStartMessage()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using Barotrauma.Networking;
|
||||||
|
using FarseerPhysics;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
partial class NestMission : Mission
|
||||||
|
{
|
||||||
|
public override void ClientReadInitial(IReadMessage msg)
|
||||||
|
{
|
||||||
|
nestPosition = new Vector2(
|
||||||
|
msg.ReadSingle(),
|
||||||
|
msg.ReadSingle());
|
||||||
|
ushort itemCount = msg.ReadUInt16();
|
||||||
|
for (int i = 0; i < itemCount; i++)
|
||||||
|
{
|
||||||
|
var item = Item.ReadSpawnData(msg);
|
||||||
|
items.Add(item);
|
||||||
|
if (item.body != null)
|
||||||
|
{
|
||||||
|
item.body.FarseerBody.BodyType = BodyType.Kinematic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1256,17 +1256,26 @@ namespace Barotrauma
|
|||||||
|
|
||||||
#region Element drawing
|
#region Element drawing
|
||||||
|
|
||||||
public static void DrawIndicator(SpriteBatch spriteBatch, Vector2 worldPosition, Camera cam, float hideDist, Sprite sprite, Color color)
|
|
||||||
|
/// <param name="createOffset">Should the indicator move based on the camera position?</param>
|
||||||
|
public static void DrawIndicator(SpriteBatch spriteBatch, Vector2 worldPosition, Camera cam, float hideDist, Sprite sprite, Color color, bool createOffset = true, float scaleMultiplier = 1.0f)
|
||||||
{
|
{
|
||||||
Vector2 diff = worldPosition - cam.WorldViewCenter;
|
Vector2 diff = worldPosition - cam.WorldViewCenter;
|
||||||
float dist = diff.Length();
|
float dist = diff.Length();
|
||||||
|
|
||||||
float symbolScale = Math.Min(64.0f / sprite.size.X, 1.0f);
|
float symbolScale = Math.Min(64.0f / sprite.size.X, 1.0f) * scaleMultiplier;
|
||||||
|
|
||||||
if (dist > hideDist)
|
if (dist > hideDist)
|
||||||
{
|
{
|
||||||
float alpha = Math.Min((dist - hideDist) / 100.0f, 1.0f);
|
float alpha = Math.Min((dist - hideDist) / 100.0f, 1.0f);
|
||||||
Vector2 targetScreenPos = cam.WorldToScreen(worldPosition);
|
Vector2 targetScreenPos = cam.WorldToScreen(worldPosition);
|
||||||
|
|
||||||
|
if (!createOffset)
|
||||||
|
{
|
||||||
|
sprite.Draw(spriteBatch, targetScreenPos, color * alpha, rotate: 0.0f, scale: symbolScale);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
float screenDist = Vector2.Distance(cam.WorldToScreen(cam.WorldViewCenter), targetScreenPos);
|
float screenDist = Vector2.Distance(cam.WorldToScreen(cam.WorldViewCenter), targetScreenPos);
|
||||||
float angle = MathUtils.VectorToAngle(diff);
|
float angle = MathUtils.VectorToAngle(diff);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
@@ -218,6 +219,12 @@ namespace Barotrauma
|
|||||||
|
|
||||||
GUI.Style.ButtonPulse.Draw(spriteBatch, expandRect, ToolBox.GradientLerp(pulseExpand, Color.White, Color.White, Color.Transparent));
|
GUI.Style.ButtonPulse.Draw(spriteBatch, expandRect, ToolBox.GradientLerp(pulseExpand, Color.White, Color.White, Color.Transparent));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (UserData is string s && s == "ReadyCheckButton" && ReadyCheck.lastReadyCheck > DateTime.Now)
|
||||||
|
{
|
||||||
|
float progress = (ReadyCheck.lastReadyCheck - DateTime.Now).Seconds / 60.0f;
|
||||||
|
Frame.Color = ToolBox.GradientLerp(progress, Color.White, GUI.Style.Red);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Update(float deltaTime)
|
protected override void Update(float deltaTime)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Microsoft.Xna.Framework.Graphics;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Barotrauma.Networking;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -20,7 +21,8 @@ namespace Barotrauma
|
|||||||
public enum Type
|
public enum Type
|
||||||
{
|
{
|
||||||
Default,
|
Default,
|
||||||
InGame
|
InGame,
|
||||||
|
Vote
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<GUIButton> Buttons { get; private set; } = new List<GUIButton>();
|
public List<GUIButton> Buttons { get; private set; } = new List<GUIButton>();
|
||||||
@@ -48,6 +50,9 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool Draggable { get; set; }
|
||||||
|
public Vector2 DraggingPosition = Vector2.Zero;
|
||||||
|
|
||||||
public GUIImage BackgroundIcon { get; private set; }
|
public GUIImage BackgroundIcon { get; private set; }
|
||||||
private GUIImage newBackgroundIcon;
|
private GUIImage newBackgroundIcon;
|
||||||
|
|
||||||
@@ -60,7 +65,7 @@ namespace Barotrauma
|
|||||||
private bool iconSwitching;
|
private bool iconSwitching;
|
||||||
private bool closing;
|
private bool closing;
|
||||||
|
|
||||||
private Type type;
|
private readonly Type type;
|
||||||
|
|
||||||
public static GUIComponent VisibleBox => MessageBoxes.LastOrDefault();
|
public static GUIComponent VisibleBox => MessageBoxes.LastOrDefault();
|
||||||
|
|
||||||
@@ -97,12 +102,25 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
InnerFrame = new GUIFrame(new RectTransform(new Point(width, height), RectTransform, type == Type.InGame ? Anchor.TopCenter : Anchor.Center) { IsFixedSize = false }, style: null);
|
Anchor anchor = type switch
|
||||||
|
{
|
||||||
|
Type.InGame => Anchor.TopCenter,
|
||||||
|
Type.Vote => Anchor.TopRight,
|
||||||
|
_ => Anchor.Center
|
||||||
|
};
|
||||||
|
|
||||||
|
InnerFrame = new GUIFrame(new RectTransform(new Point(width, height), RectTransform, anchor) { IsFixedSize = false }, style: null);
|
||||||
|
if (type == Type.Vote)
|
||||||
|
{
|
||||||
|
int offset = GUI.IntScale(64);
|
||||||
|
InnerFrame.RectTransform.ScreenSpaceOffset = new Point(-offset, offset);
|
||||||
|
CanBeFocused = false;
|
||||||
|
}
|
||||||
GUI.Style.Apply(InnerFrame, "", this);
|
GUI.Style.Apply(InnerFrame, "", this);
|
||||||
this.type = type;
|
this.type = type;
|
||||||
Tag = tag;
|
Tag = tag;
|
||||||
|
|
||||||
if (type == Type.Default)
|
if (type == Type.Default || type == Type.Vote)
|
||||||
{
|
{
|
||||||
Content = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.85f), InnerFrame.RectTransform, Anchor.Center)) { AbsoluteSpacing = 5 };
|
Content = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.85f), InnerFrame.RectTransform, Anchor.Center)) { AbsoluteSpacing = 5 };
|
||||||
|
|
||||||
@@ -271,92 +289,114 @@ namespace Barotrauma
|
|||||||
|
|
||||||
protected override void Update(float deltaTime)
|
protected override void Update(float deltaTime)
|
||||||
{
|
{
|
||||||
if (type != Type.InGame) { return; }
|
if (Draggable)
|
||||||
|
|
||||||
Vector2 initialPos = new Vector2(0.0f, GameMain.GraphicsHeight);
|
|
||||||
Vector2 defaultPos = new Vector2(0.0f, HUDLayoutSettings.InventoryAreaLower.Y - InnerFrame.Rect.Height - 20 * GUI.Scale);
|
|
||||||
Vector2 endPos = new Vector2(GameMain.GraphicsWidth, defaultPos.Y);
|
|
||||||
|
|
||||||
if (!closing)
|
|
||||||
{
|
{
|
||||||
Point step = Vector2.SmoothStep(initialPos, defaultPos, openState).ToPoint();
|
if ((GUI.MouseOn == InnerFrame || InnerFrame.IsParentOf(GUI.MouseOn)) && !(GUI.MouseOn is GUIButton))
|
||||||
InnerFrame.RectTransform.AbsoluteOffset = step;
|
|
||||||
if (BackgroundIcon != null)
|
|
||||||
{
|
{
|
||||||
BackgroundIcon.RectTransform.AbsoluteOffset = new Point(InnerFrame.Rect.Location.X - (int) (BackgroundIcon.Rect.Size.X / 1.25f), (int)defaultPos.Y - BackgroundIcon.Rect.Size.Y / 2);
|
GUI.MouseCursor = CursorState.Move;
|
||||||
if (!MathUtils.NearlyEqual(openState, 1.0f))
|
if (PlayerInput.PrimaryMouseButtonDown())
|
||||||
{
|
{
|
||||||
BackgroundIcon.Color = ToolBox.GradientLerp(openState, Color.Transparent, Color.White);
|
DraggingPosition = RectTransform.ScreenSpaceOffset.ToVector2() - PlayerInput.MousePosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!(Screen.Selected is RoundSummaryScreen) && !MessageBoxes.Any(mb => mb.UserData is RoundSummary))
|
|
||||||
{
|
|
||||||
openState = Math.Min(openState + deltaTime * 2.0f, 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GUI.MouseOn != InnerFrame && !InnerFrame.IsParentOf(GUI.MouseOn) && AutoClose)
|
if (PlayerInput.PrimaryMouseButtonHeld() && DraggingPosition != Vector2.Zero)
|
||||||
{
|
{
|
||||||
inGameCloseTimer += deltaTime;
|
GUI.MouseCursor = CursorState.Dragging;
|
||||||
}
|
RectTransform.ScreenSpaceOffset = (PlayerInput.MousePosition + DraggingPosition).ToPoint();
|
||||||
|
|
||||||
if (inGameCloseTimer >= inGameCloseTime)
|
|
||||||
{
|
|
||||||
Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
openState += deltaTime * 2.0f;
|
|
||||||
Point step = Vector2.SmoothStep(defaultPos, endPos, openState - 1.0f).ToPoint();
|
|
||||||
InnerFrame.RectTransform.AbsoluteOffset = step;
|
|
||||||
if (BackgroundIcon != null)
|
|
||||||
{
|
|
||||||
BackgroundIcon.Color *= 0.9f;
|
|
||||||
}
|
|
||||||
if (openState >= 2.0f)
|
|
||||||
{
|
|
||||||
if (Parent != null) { Parent.RemoveChild(this); }
|
|
||||||
if (MessageBoxes.Contains(this)) { MessageBoxes.Remove(this); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newBackgroundIcon != null)
|
|
||||||
{
|
|
||||||
if (!iconSwitching)
|
|
||||||
{
|
|
||||||
if (BackgroundIcon != null)
|
|
||||||
{
|
|
||||||
BackgroundIcon.Color *= 0.9f;
|
|
||||||
if (BackgroundIcon.Color.A == 0)
|
|
||||||
{
|
|
||||||
BackgroundIcon = null;
|
|
||||||
iconSwitching = true;
|
|
||||||
RemoveChild(BackgroundIcon);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
iconSwitching = true;
|
|
||||||
}
|
|
||||||
iconState = 0;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
newBackgroundIcon.SetAsFirstChild();
|
DraggingPosition = Vector2.Zero;
|
||||||
newBackgroundIcon.RectTransform.AbsoluteOffset = new Point(InnerFrame.Rect.Location.X - (int) (newBackgroundIcon.Rect.Size.X / 1.25f), (int)defaultPos.Y - newBackgroundIcon.Rect.Size.Y / 2);
|
|
||||||
newBackgroundIcon.Color = ToolBox.GradientLerp(iconState, Color.Transparent, Color.White);
|
|
||||||
if (newBackgroundIcon.Color.A == 255)
|
|
||||||
{
|
|
||||||
BackgroundIcon = newBackgroundIcon;
|
|
||||||
BackgroundIcon.SetAsFirstChild();
|
|
||||||
newBackgroundIcon = null;
|
|
||||||
iconSwitching = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
iconState = Math.Min(iconState + deltaTime * 2.0f, 1.0f);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type == Type.InGame)
|
||||||
|
{
|
||||||
|
Vector2 initialPos = new Vector2(0.0f, GameMain.GraphicsHeight);
|
||||||
|
Vector2 defaultPos = new Vector2(0.0f, HUDLayoutSettings.InventoryAreaLower.Y - InnerFrame.Rect.Height - 20 * GUI.Scale);
|
||||||
|
Vector2 endPos = new Vector2(GameMain.GraphicsWidth, defaultPos.Y);
|
||||||
|
|
||||||
|
if (!closing)
|
||||||
|
{
|
||||||
|
Point step = Vector2.SmoothStep(initialPos, defaultPos, openState).ToPoint();
|
||||||
|
InnerFrame.RectTransform.AbsoluteOffset = step;
|
||||||
|
if (BackgroundIcon != null)
|
||||||
|
{
|
||||||
|
BackgroundIcon.RectTransform.AbsoluteOffset = new Point(InnerFrame.Rect.Location.X - (int)(BackgroundIcon.Rect.Size.X / 1.25f), (int)defaultPos.Y - BackgroundIcon.Rect.Size.Y / 2);
|
||||||
|
if (!MathUtils.NearlyEqual(openState, 1.0f))
|
||||||
|
{
|
||||||
|
BackgroundIcon.Color = ToolBox.GradientLerp(openState, Color.Transparent, Color.White);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!(Screen.Selected is RoundSummaryScreen) && !MessageBoxes.Any(mb => mb.UserData is RoundSummary))
|
||||||
|
{
|
||||||
|
openState = Math.Min(openState + deltaTime * 2.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUI.MouseOn != InnerFrame && !InnerFrame.IsParentOf(GUI.MouseOn) && AutoClose)
|
||||||
|
{
|
||||||
|
inGameCloseTimer += deltaTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inGameCloseTimer >= inGameCloseTime)
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
openState += deltaTime * 2.0f;
|
||||||
|
Point step = Vector2.SmoothStep(defaultPos, endPos, openState - 1.0f).ToPoint();
|
||||||
|
InnerFrame.RectTransform.AbsoluteOffset = step;
|
||||||
|
if (BackgroundIcon != null)
|
||||||
|
{
|
||||||
|
BackgroundIcon.Color *= 0.9f;
|
||||||
|
}
|
||||||
|
if (openState >= 2.0f)
|
||||||
|
{
|
||||||
|
if (Parent != null) { Parent.RemoveChild(this); }
|
||||||
|
if (MessageBoxes.Contains(this)) { MessageBoxes.Remove(this); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newBackgroundIcon != null)
|
||||||
|
{
|
||||||
|
if (!iconSwitching)
|
||||||
|
{
|
||||||
|
if (BackgroundIcon != null)
|
||||||
|
{
|
||||||
|
BackgroundIcon.Color *= 0.9f;
|
||||||
|
if (BackgroundIcon.Color.A == 0)
|
||||||
|
{
|
||||||
|
BackgroundIcon = null;
|
||||||
|
iconSwitching = true;
|
||||||
|
RemoveChild(BackgroundIcon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iconSwitching = true;
|
||||||
|
}
|
||||||
|
iconState = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newBackgroundIcon.SetAsFirstChild();
|
||||||
|
newBackgroundIcon.RectTransform.AbsoluteOffset = new Point(InnerFrame.Rect.Location.X - (int)(newBackgroundIcon.Rect.Size.X / 1.25f), (int)defaultPos.Y - newBackgroundIcon.Rect.Size.Y / 2);
|
||||||
|
newBackgroundIcon.Color = ToolBox.GradientLerp(iconState, Color.Transparent, Color.White);
|
||||||
|
if (newBackgroundIcon.Color.A == 255)
|
||||||
|
{
|
||||||
|
BackgroundIcon = newBackgroundIcon;
|
||||||
|
BackgroundIcon.SetAsFirstChild();
|
||||||
|
newBackgroundIcon = null;
|
||||||
|
iconSwitching = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
iconState = Math.Min(iconState + deltaTime * 2.0f, 1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -707,6 +707,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private void SortItems(GUIListBox list, SortingMethod sortingMethod)
|
private void SortItems(GUIListBox list, SortingMethod sortingMethod)
|
||||||
{
|
{
|
||||||
|
if (CurrentLocation == null) { return; }
|
||||||
|
|
||||||
if (sortingMethod == SortingMethod.AlphabeticalAsc || sortingMethod == SortingMethod.AlphabeticalDesc)
|
if (sortingMethod == SortingMethod.AlphabeticalAsc || sortingMethod == SortingMethod.AlphabeticalDesc)
|
||||||
{
|
{
|
||||||
list.Content.RectTransform.SortChildren(
|
list.Content.RectTransform.SortChildren(
|
||||||
@@ -868,13 +870,13 @@ namespace Barotrauma
|
|||||||
TextColor = Color.White * (forceDisable ? 0.5f : 1.0f),
|
TextColor = Color.White * (forceDisable ? 0.5f : 1.0f),
|
||||||
UserData = "price"
|
UserData = "price"
|
||||||
};
|
};
|
||||||
if(listBox == storeSellList || listBox == shoppingCrateSellList)
|
if (listBox == storeSellList || listBox == shoppingCrateSellList)
|
||||||
{
|
{
|
||||||
priceBlock.TextGetter = () => GetCurrencyFormatted(CurrentLocation.GetAdjustedItemSellPrice(priceInfo));
|
priceBlock.TextGetter = () => GetCurrencyFormatted(CurrentLocation?.GetAdjustedItemSellPrice(priceInfo) ?? 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
priceBlock.TextGetter = () => GetCurrencyFormatted(CurrentLocation.GetAdjustedItemBuyPrice(priceInfo));
|
priceBlock.TextGetter = () => GetCurrencyFormatted(CurrentLocation?.GetAdjustedItemBuyPrice(priceInfo) ?? 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listBox == storeDealsList || listBox == storeBuyList || listBox == storeSellList)
|
if (listBox == storeDealsList || listBox == storeBuyList || listBox == storeSellList)
|
||||||
|
|||||||
@@ -525,6 +525,7 @@ namespace Barotrauma
|
|||||||
Tutorials.Tutorial.Init();
|
Tutorials.Tutorial.Init();
|
||||||
MapGenerationParams.Init();
|
MapGenerationParams.Init();
|
||||||
LevelGenerationParams.LoadPresets();
|
LevelGenerationParams.LoadPresets();
|
||||||
|
CaveGenerationParams.LoadPresets();
|
||||||
OutpostGenerationParams.LoadPresets();
|
OutpostGenerationParams.LoadPresets();
|
||||||
WreckAIConfig.LoadAll();
|
WreckAIConfig.LoadAll();
|
||||||
EventSet.LoadPrefabs();
|
EventSet.LoadPrefabs();
|
||||||
@@ -533,6 +534,7 @@ namespace Barotrauma
|
|||||||
SkillSettings.Load(GetFilesOfType(ContentType.SkillSettings));
|
SkillSettings.Load(GetFilesOfType(ContentType.SkillSettings));
|
||||||
Order.Init();
|
Order.Init();
|
||||||
EventManagerSettings.Init();
|
EventManagerSettings.Init();
|
||||||
|
BallastFloraPrefab.LoadAll(GetFilesOfType(ContentType.MapCreature));
|
||||||
TitleScreen.LoadState = 50.0f;
|
TitleScreen.LoadState = 50.0f;
|
||||||
yield return CoroutineStatus.Running;
|
yield return CoroutineStatus.Running;
|
||||||
|
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var reports = Order.PrefabList.FindAll(o => o.TargetAllCharacters && o.SymbolSprite != null);
|
var reports = Order.PrefabList.FindAll(o => o.IsReport && o.SymbolSprite != null);
|
||||||
if (reports.None())
|
if (reports.None())
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("No valid orders for report buttons found! Cannot create report buttons. The orders for the report buttons must have 'targetallcharacters' attribute enabled and a valid 'symbolsprite' defined.");
|
DebugConsole.ThrowError("No valid orders for report buttons found! Cannot create report buttons. The orders for the report buttons must have 'targetallcharacters' attribute enabled and a valid 'symbolsprite' defined.");
|
||||||
@@ -252,7 +252,7 @@ namespace Barotrauma
|
|||||||
//report buttons
|
//report buttons
|
||||||
foreach (Order order in reports)
|
foreach (Order order in reports)
|
||||||
{
|
{
|
||||||
if (!order.TargetAllCharacters || order.SymbolSprite == null) { continue; }
|
if (!order.IsReport || order.SymbolSprite == null) { continue; }
|
||||||
var btn = new GUIButton(new RectTransform(new Point(ReportButtonFrame.Rect.Width), ReportButtonFrame.RectTransform), style: null)
|
var btn = new GUIButton(new RectTransform(new Point(ReportButtonFrame.Rect.Width), ReportButtonFrame.RectTransform), style: null)
|
||||||
{
|
{
|
||||||
OnClicked = (GUIButton button, object userData) =>
|
OnClicked = (GUIButton button, object userData) =>
|
||||||
@@ -667,6 +667,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
#region Crew List Order Displayment
|
#region Crew List Order Displayment
|
||||||
|
|
||||||
|
// TODO: CHECK ALL THE ORDER CONSTUCTOR CALLS
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the character's current order (if it's close enough to receive messages from orderGiver) and
|
/// Sets the character's current order (if it's close enough to receive messages from orderGiver) and
|
||||||
/// displays the order in the crew UI
|
/// displays the order in the crew UI
|
||||||
@@ -675,16 +677,69 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (order != null && order.TargetAllCharacters)
|
if (order != null && order.TargetAllCharacters)
|
||||||
{
|
{
|
||||||
if (orderGiver == null || orderGiver.CurrentHull == null) { return; }
|
Hull hull = null;
|
||||||
var hull = orderGiver.CurrentHull;
|
if (order.IsReport)
|
||||||
AddOrder(new Order(order.Prefab ?? order, hull, null, orderGiver), order.FadeOutTime);
|
{
|
||||||
|
if (orderGiver?.CurrentHull == null) { return; }
|
||||||
|
hull = orderGiver.CurrentHull;
|
||||||
|
AddOrder(new Order(order.Prefab ?? order, hull, null, orderGiver), order.FadeOutTime);
|
||||||
|
}
|
||||||
|
else if(order.IsIgnoreOrder)
|
||||||
|
{
|
||||||
|
WallSection ws = null;
|
||||||
|
if (order.TargetType == Order.OrderTargetType.Entity && order.TargetEntity is MapEntity me)
|
||||||
|
{
|
||||||
|
if (order.Identifier == "ignorethis")
|
||||||
|
{
|
||||||
|
me.SetIgnoreByAI(true);
|
||||||
|
AddOrder(new Order(order.Prefab ?? order, order.TargetEntity, order.TargetItemComponent, orderGiver), null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
me.SetIgnoreByAI(false);
|
||||||
|
ActiveOrders.RemoveAll(p => p.First.Identifier == "ignorethis" && p.First.TargetEntity == order.TargetEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (order.TargetType == Order.OrderTargetType.WallSection && order.TargetEntity is Structure s)
|
||||||
|
{
|
||||||
|
var wallSectionIndex = order.WallSectionIndex ?? s.Sections.IndexOf(wallContext);
|
||||||
|
ws = s.GetSection(wallSectionIndex);
|
||||||
|
if (ws != null)
|
||||||
|
{
|
||||||
|
if (order.Identifier == "ignorethis")
|
||||||
|
{
|
||||||
|
ws.SetIgnoreByAI(true);
|
||||||
|
AddOrder(new Order(order.Prefab ?? order, s, wallSectionIndex, orderGiver), null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ws.SetIgnoreByAI(false);
|
||||||
|
ActiveOrders.RemoveAll(p => p.First.Identifier == "ignorethis" && p.First.TargetEntity == s && p.First.WallSectionIndex == wallSectionIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ws != null)
|
||||||
|
{
|
||||||
|
hull = Hull.FindHull(ws.WorldPosition);
|
||||||
|
}
|
||||||
|
else if (order.TargetEntity is Item i)
|
||||||
|
{
|
||||||
|
hull = i.CurrentHull;
|
||||||
|
}
|
||||||
|
else if (order.TargetEntity is ISpatialEntity se)
|
||||||
|
{
|
||||||
|
hull = Hull.FindHull(se.WorldPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (IsSinglePlayer)
|
if (IsSinglePlayer)
|
||||||
{
|
{
|
||||||
orderGiver.Speak(order.GetChatMessage("", hull.DisplayName, givingOrderToSelf: character == orderGiver), ChatMessageType.Order);
|
orderGiver.Speak(order.GetChatMessage("", hull?.DisplayName, givingOrderToSelf: character == orderGiver), ChatMessageType.Order);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
OrderChatMessage msg = new OrderChatMessage(order, "", hull, null, orderGiver);
|
OrderChatMessage msg = new OrderChatMessage(order, "", order.IsReport ? hull : order.TargetEntity, null, orderGiver);
|
||||||
GameMain.Client?.SendChatMessage(msg);
|
GameMain.Client?.SendChatMessage(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -696,7 +751,7 @@ namespace Barotrauma
|
|||||||
if (IsSinglePlayer)
|
if (IsSinglePlayer)
|
||||||
{
|
{
|
||||||
character.SetOrder(order, option, orderGiver, speak: orderGiver != character);
|
character.SetOrder(order, option, orderGiver, speak: orderGiver != character);
|
||||||
orderGiver?.Speak(order.GetChatMessage(character.Name, orderGiver.CurrentHull?.DisplayName, givingOrderToSelf: character == orderGiver, orderOption: option), null);
|
orderGiver?.Speak(order?.GetChatMessage(character.Name, orderGiver.CurrentHull?.DisplayName, givingOrderToSelf: character == orderGiver, orderOption: option));
|
||||||
}
|
}
|
||||||
else if (orderGiver != null)
|
else if (orderGiver != null)
|
||||||
{
|
{
|
||||||
@@ -1591,6 +1646,7 @@ namespace Barotrauma
|
|||||||
private Character characterContext;
|
private Character characterContext;
|
||||||
private Item itemContext;
|
private Item itemContext;
|
||||||
private Hull hullContext;
|
private Hull hullContext;
|
||||||
|
private WallSection wallContext;
|
||||||
private bool isContextual;
|
private bool isContextual;
|
||||||
private readonly List<Order> contextualOrders = new List<Order>();
|
private readonly List<Order> contextualOrders = new List<Order>();
|
||||||
private Point shorcutCenterNodeOffset;
|
private Point shorcutCenterNodeOffset;
|
||||||
@@ -1640,7 +1696,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (TryGetBreachedHullAtHoveredWall(out Hull breachedHull))
|
else if (TryGetBreachedHullAtHoveredWall(out Hull breachedHull, out wallContext))
|
||||||
{
|
{
|
||||||
return breachedHull;
|
return breachedHull;
|
||||||
}
|
}
|
||||||
@@ -1662,16 +1718,24 @@ namespace Barotrauma
|
|||||||
if (entityContext is Character character)
|
if (entityContext is Character character)
|
||||||
{
|
{
|
||||||
characterContext = character;
|
characterContext = character;
|
||||||
|
itemContext = null;
|
||||||
|
hullContext = null;
|
||||||
|
wallContext = null;
|
||||||
isContextual = false;
|
isContextual = false;
|
||||||
}
|
}
|
||||||
else if (entityContext is Item item)
|
else if (entityContext is Item item)
|
||||||
{
|
{
|
||||||
itemContext = item;
|
itemContext = item;
|
||||||
|
characterContext = null;
|
||||||
|
hullContext = null;
|
||||||
|
wallContext = null;
|
||||||
isContextual = true;
|
isContextual = true;
|
||||||
}
|
}
|
||||||
else if (entityContext is Hull hull)
|
else if (entityContext is Hull hull)
|
||||||
{
|
{
|
||||||
hullContext = hull;
|
hullContext = hull;
|
||||||
|
characterContext = null;
|
||||||
|
itemContext = null;
|
||||||
isContextual = true;
|
isContextual = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1785,7 +1849,7 @@ namespace Barotrauma
|
|||||||
availableCategories = new List<OrderCategory>();
|
availableCategories = new List<OrderCategory>();
|
||||||
foreach (OrderCategory category in Enum.GetValues(typeof(OrderCategory)))
|
foreach (OrderCategory category in Enum.GetValues(typeof(OrderCategory)))
|
||||||
{
|
{
|
||||||
if (Order.PrefabList.Any(o => o.Category == category && !o.TargetAllCharacters))
|
if (Order.PrefabList.Any(o => o.Category == category && !o.IsReport))
|
||||||
{
|
{
|
||||||
availableCategories.Add(category);
|
availableCategories.Add(category);
|
||||||
}
|
}
|
||||||
@@ -2129,7 +2193,7 @@ namespace Barotrauma
|
|||||||
if (Order.GetPrefab(orderIdentifier) is Order orderPrefab &&
|
if (Order.GetPrefab(orderIdentifier) is Order orderPrefab &&
|
||||||
shortcutNodes.None(n => (n.UserData is Order order && order.Identifier == orderIdentifier) ||
|
shortcutNodes.None(n => (n.UserData is Order order && order.Identifier == orderIdentifier) ||
|
||||||
(n.UserData is Tuple<Order, string> orderWithOption && orderWithOption.Item1.Identifier == orderIdentifier)) &&
|
(n.UserData is Tuple<Order, string> orderWithOption && orderWithOption.Item1.Identifier == orderIdentifier)) &&
|
||||||
!orderPrefab.TargetAllCharacters && orderPrefab.Category != null)
|
!orderPrefab.IsReport && orderPrefab.Category != null)
|
||||||
{
|
{
|
||||||
if (!orderPrefab.MustSetTarget || orderPrefab.GetMatchingItems(sub, true).Any())
|
if (!orderPrefab.MustSetTarget || orderPrefab.GetMatchingItems(sub, true).Any())
|
||||||
{
|
{
|
||||||
@@ -2172,7 +2236,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private void CreateOrderNodes(OrderCategory orderCategory)
|
private void CreateOrderNodes(OrderCategory orderCategory)
|
||||||
{
|
{
|
||||||
var orders = Order.PrefabList.FindAll(o => o.Category == orderCategory && !o.TargetAllCharacters);
|
var orders = Order.PrefabList.FindAll(o => o.Category == orderCategory && !o.IsReport);
|
||||||
Order order;
|
Order order;
|
||||||
bool disableNode;
|
bool disableNode;
|
||||||
var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, nodeDistance,
|
var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, nodeDistance,
|
||||||
@@ -2255,29 +2319,33 @@ namespace Barotrauma
|
|||||||
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), itemContext, targetItem: null, Character.Controlled));
|
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), itemContext, targetItem: null, Character.Controlled));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AddIgnoreOrder(itemContext);
|
||||||
}
|
}
|
||||||
else if (hullContext != null)
|
else if (hullContext != null)
|
||||||
{
|
{
|
||||||
contextualOrders.Add(new Order(Order.GetPrefab("fixleaks"), hullContext, targetItem: null, Character.Controlled));
|
contextualOrders.Add(new Order(Order.GetPrefab("fixleaks"), hullContext, targetItem: null, Character.Controlled));
|
||||||
|
|
||||||
|
if (wallContext != null)
|
||||||
|
{
|
||||||
|
AddIgnoreOrder(wallContext);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contextualOrders.None(o => o.Category != OrderCategory.Movement))
|
orderIdentifier = "wait";
|
||||||
|
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)))
|
||||||
{
|
{
|
||||||
orderIdentifier = "wait";
|
Vector2 position = GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||||
|
Hull hull = Hull.FindHull(position, guess: Character.Controlled?.CurrentHull);
|
||||||
|
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), new OrderTarget(position, hull), Character.Controlled));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contextualOrders.None(o => o.Category != OrderCategory.Movement) && characters.Any(c => c != Character.Controlled))
|
||||||
|
{
|
||||||
|
orderIdentifier = "follow";
|
||||||
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)))
|
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)))
|
||||||
{
|
{
|
||||||
Vector2 position = GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
|
contextualOrders.Add(Order.GetPrefab(orderIdentifier));
|
||||||
Hull hull = Hull.FindHull(position, guess: Character.Controlled?.CurrentHull);
|
|
||||||
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), new OrderTarget(position, hull), Character.Controlled));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (characters.Any(c => c != Character.Controlled))
|
|
||||||
{
|
|
||||||
orderIdentifier = "follow";
|
|
||||||
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)))
|
|
||||||
{
|
|
||||||
contextualOrders.Add(Order.GetPrefab(orderIdentifier));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2298,6 +2366,35 @@ namespace Barotrauma
|
|||||||
CreateOrderNode(nodeSize, commandFrame.RectTransform, offsets[i].ToPoint(), contextualOrders[i], (i + 1) % 10, disableNode: disableNode, checkIfOrderCanBeHeard: false),
|
CreateOrderNode(nodeSize, commandFrame.RectTransform, offsets[i].ToPoint(), contextualOrders[i], (i + 1) % 10, disableNode: disableNode, checkIfOrderCanBeHeard: false),
|
||||||
!disableNode ? Keys.D0 + (i + 1) % 10 : Keys.None));
|
!disableNode ? Keys.D0 + (i + 1) % 10 : Keys.None));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AddIgnoreOrder(ISpatialEntity target)
|
||||||
|
{
|
||||||
|
var orderIdentifier = "ignorethis";
|
||||||
|
if (!target.IgnoreByAI && contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)))
|
||||||
|
{
|
||||||
|
AddOrder(orderIdentifier, target);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
orderIdentifier = "unignorethis";
|
||||||
|
if (target.IgnoreByAI && contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)))
|
||||||
|
{
|
||||||
|
AddOrder(orderIdentifier, target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddOrder(string id, ISpatialEntity target)
|
||||||
|
{
|
||||||
|
if (target is WallSection ws)
|
||||||
|
{
|
||||||
|
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), ws.Wall, ws.Wall.Sections.IndexOf(ws), orderGiver: Character.Controlled));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), target as Entity, null, Character.Controlled));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: there's duplicate logic here and above -> would be better to refactor so that the conditions are only defined in one place
|
// TODO: there's duplicate logic here and above -> would be better to refactor so that the conditions are only defined in one place
|
||||||
@@ -2367,11 +2464,13 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
o = new Order(o.Prefab, orderTargetEntity, orderTargetEntity.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType), orderGiver: order.OrderGiver);
|
o = new Order(o.Prefab, orderTargetEntity, orderTargetEntity.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType), orderGiver: order.OrderGiver);
|
||||||
}
|
}
|
||||||
SetCharacterOrder(characterContext ?? GetCharacterForQuickAssignment(o), o, null, Character.Controlled);
|
var character = !o.TargetAllCharacters ? characterContext ?? GetCharacterForQuickAssignment(o) : null;
|
||||||
|
SetCharacterOrder(character, o, null, Character.Controlled);
|
||||||
DisableCommandUI();
|
DisableCommandUI();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
// TODO: Might need to edit the tooltip
|
||||||
var icon = CreateNodeIcon(node.RectTransform, order.SymbolSprite, order.Color,
|
var icon = CreateNodeIcon(node.RectTransform, order.SymbolSprite, order.Color,
|
||||||
tooltip: mustSetOptionOrTarget || characterContext != null ? order.Name : order.Name +
|
tooltip: mustSetOptionOrTarget || characterContext != null ? order.Name : order.Name +
|
||||||
"\n" + (!PlayerInput.MouseButtonsSwapped() ? TextManager.Get("input.leftmouse") : TextManager.Get("input.rightmouse")) + ": " + TextManager.Get("commandui.quickassigntooltip") +
|
"\n" + (!PlayerInput.MouseButtonsSwapped() ? TextManager.Get("input.leftmouse") : TextManager.Get("input.rightmouse")) + ": " + TextManager.Get("commandui.quickassigntooltip") +
|
||||||
@@ -2948,9 +3047,10 @@ namespace Barotrauma
|
|||||||
return (degrees < 0) ? (degrees + 360) : degrees;
|
return (degrees < 0) ? (degrees + 360) : degrees;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryGetBreachedHullAtHoveredWall(out Hull breachedHull)
|
private bool TryGetBreachedHullAtHoveredWall(out Hull breachedHull, out WallSection hoveredWall)
|
||||||
{
|
{
|
||||||
breachedHull = null;
|
breachedHull = null;
|
||||||
|
hoveredWall = null;
|
||||||
// Based on the IsValidTarget() method of AIObjectiveFixLeaks class
|
// Based on the IsValidTarget() method of AIObjectiveFixLeaks class
|
||||||
List<Gap> leaks = Gap.GapList.FindAll(g =>
|
List<Gap> leaks = Gap.GapList.FindAll(g =>
|
||||||
g != null && g.ConnectedWall != null && g.ConnectedDoor == null && g.Open > 0 && g.linkedTo.Any(l => l != null) &&
|
g != null && g.ConnectedWall != null && g.ConnectedDoor == null && g.Open > 0 && g.linkedTo.Any(l => l != null) &&
|
||||||
@@ -2962,6 +3062,15 @@ namespace Barotrauma
|
|||||||
if (Submarine.RectContains(leak.ConnectedWall.WorldRect, mouseWorldPosition))
|
if (Submarine.RectContains(leak.ConnectedWall.WorldRect, mouseWorldPosition))
|
||||||
{
|
{
|
||||||
breachedHull = leak.FlowTargetHull;
|
breachedHull = leak.FlowTargetHull;
|
||||||
|
foreach (var section in leak.ConnectedWall.Sections)
|
||||||
|
{
|
||||||
|
if (Submarine.RectContains(section.WorldRect, mouseWorldPosition))
|
||||||
|
{
|
||||||
|
hoveredWall = section;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
protected GUIButton endRoundButton;
|
protected GUIButton endRoundButton;
|
||||||
|
|
||||||
|
public GUIButton ReadyCheckButton;
|
||||||
public GUIButton EndRoundButton => endRoundButton;
|
public GUIButton EndRoundButton => endRoundButton;
|
||||||
|
|
||||||
protected GUIFrame campaignUIContainer;
|
protected GUIFrame campaignUIContainer;
|
||||||
@@ -143,6 +144,7 @@ namespace Barotrauma
|
|||||||
if (GUI.DisableHUD || GUI.DisableUpperHUD || ForceMapUI || CoroutineManager.IsCoroutineRunning("LevelTransition"))
|
if (GUI.DisableHUD || GUI.DisableUpperHUD || ForceMapUI || CoroutineManager.IsCoroutineRunning("LevelTransition"))
|
||||||
{
|
{
|
||||||
endRoundButton.Visible = false;
|
endRoundButton.Visible = false;
|
||||||
|
if (ReadyCheckButton != null) { ReadyCheckButton.Visible = false; }
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (Submarine.MainSub == null) { return; }
|
if (Submarine.MainSub == null) { return; }
|
||||||
@@ -188,6 +190,8 @@ namespace Barotrauma
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ReadyCheckButton != null) { ReadyCheckButton.Visible = endRoundButton.Visible; }
|
||||||
|
|
||||||
if (endRoundButton.Visible)
|
if (endRoundButton.Visible)
|
||||||
{
|
{
|
||||||
if (!AllowedToEndRound()) { buttonText = TextManager.Get("map"); }
|
if (!AllowedToEndRound()) { buttonText = TextManager.Get("map"); }
|
||||||
@@ -211,6 +215,10 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
endRoundButton.DrawManually(spriteBatch);
|
endRoundButton.DrawManually(spriteBatch);
|
||||||
|
if (this is MultiPlayerCampaign)
|
||||||
|
{
|
||||||
|
ReadyCheckButton?.DrawManually(spriteBatch);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task SelectSummaryScreen(RoundSummary roundSummary, LevelData newLevel, bool mirror, Action action)
|
public Task SelectSummaryScreen(RoundSummary roundSummary, LevelData newLevel, bool mirror, Action action)
|
||||||
@@ -279,6 +287,7 @@ namespace Barotrauma
|
|||||||
base.AddToGUIUpdateList();
|
base.AddToGUIUpdateList();
|
||||||
CrewManager.AddToGUIUpdateList();
|
CrewManager.AddToGUIUpdateList();
|
||||||
endRoundButton.AddToGUIUpdateList();
|
endRoundButton.AddToGUIUpdateList();
|
||||||
|
ReadyCheckButton?.AddToGUIUpdateList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update(float deltaTime)
|
public override void Update(float deltaTime)
|
||||||
|
|||||||
+25
-4
@@ -34,7 +34,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void StartCampaignSetup(IEnumerable<string> saveFiles)
|
public static void StartCampaignSetup(IEnumerable<string> saveFiles)
|
||||||
{
|
{
|
||||||
var parent = GameMain.NetLobbyScreen.CampaignSetupFrame;
|
var parent = GameMain.NetLobbyScreen.CampaignSetupFrame;
|
||||||
@@ -104,10 +103,12 @@ namespace Barotrauma
|
|||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
|
|
||||||
int buttonHeight = (int)(GUI.Scale * 40);
|
int buttonHeight = (int) (GUI.Scale * 40),
|
||||||
int buttonWidth = GUI.IntScale(450);
|
buttonWidth = GUI.IntScale(450),
|
||||||
|
buttonCenter = buttonHeight / 2,
|
||||||
|
screenMiddle = GameMain.GraphicsWidth / 2;
|
||||||
|
|
||||||
endRoundButton = new GUIButton(HUDLayoutSettings.ToRectTransform(new Rectangle((GameMain.GraphicsWidth / 2) - (buttonWidth / 2), HUDLayoutSettings.ButtonAreaTop.Center.Y - (buttonHeight / 2), buttonWidth, buttonHeight), GUICanvas.Instance),
|
endRoundButton = new GUIButton(HUDLayoutSettings.ToRectTransform(new Rectangle(screenMiddle - buttonWidth / 2, HUDLayoutSettings.ButtonAreaTop.Center.Y - buttonCenter, buttonWidth, buttonHeight), GUICanvas.Instance),
|
||||||
TextManager.Get("EndRound"), textAlignment: Alignment.Center, style: "EndRoundButton")
|
TextManager.Get("EndRound"), textAlignment: Alignment.Center, style: "EndRoundButton")
|
||||||
{
|
{
|
||||||
Pulse = true,
|
Pulse = true,
|
||||||
@@ -140,6 +141,25 @@ namespace Barotrauma
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int readyButtonHeight = buttonHeight;
|
||||||
|
int readyButtonWidth = (int) (GUI.Scale * 50);
|
||||||
|
|
||||||
|
ReadyCheckButton = new GUIButton(HUDLayoutSettings.ToRectTransform(new Rectangle(screenMiddle + (buttonWidth / 2) + GUI.IntScale(16), HUDLayoutSettings.ButtonAreaTop.Center.Y - buttonCenter, readyButtonWidth, readyButtonHeight), GUICanvas.Instance),
|
||||||
|
style: "RepairBuyButton")
|
||||||
|
{
|
||||||
|
ToolTip = TextManager.Get("ReadyCheck.Tooltip"),
|
||||||
|
OnClicked = delegate
|
||||||
|
{
|
||||||
|
if (CrewManager != null && CrewManager.ActiveReadyCheck == null)
|
||||||
|
{
|
||||||
|
ReadyCheck.CreateReadyCheck();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
UserData = "ReadyCheckButton"
|
||||||
|
};
|
||||||
|
|
||||||
buttonContainer.Recalculate();
|
buttonContainer.Recalculate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,6 +398,7 @@ namespace Barotrauma
|
|||||||
if (!GUI.DisableHUD && !GUI.DisableUpperHUD)
|
if (!GUI.DisableHUD && !GUI.DisableUpperHUD)
|
||||||
{
|
{
|
||||||
endRoundButton.UpdateManually(deltaTime);
|
endRoundButton.UpdateManually(deltaTime);
|
||||||
|
ReadyCheckButton?.UpdateManually(deltaTime);
|
||||||
if (CoroutineManager.IsCoroutineRunning("LevelTransition") || ForceMapUI) { return; }
|
if (CoroutineManager.IsCoroutineRunning("LevelTransition") || ForceMapUI) { return; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-1
@@ -368,6 +368,9 @@ namespace Barotrauma
|
|||||||
SoundPlayer.OverrideMusicDuration = 18.0f;
|
SoundPlayer.OverrideMusicDuration = 18.0f;
|
||||||
crewDead = false;
|
crewDead = false;
|
||||||
|
|
||||||
|
LevelData lvlData = GameMain.GameSession.LevelData;
|
||||||
|
bool beaconActive = GameMain.GameSession.Level.CheckBeaconActive();
|
||||||
|
|
||||||
GameMain.GameSession.EndRound("", traitorResults, transitionType);
|
GameMain.GameSession.EndRound("", traitorResults, transitionType);
|
||||||
var continueButton = GameMain.GameSession.RoundSummary?.ContinueButton;
|
var continueButton = GameMain.GameSession.RoundSummary?.ContinueButton;
|
||||||
RoundSummary roundSummary = null;
|
RoundSummary roundSummary = null;
|
||||||
@@ -452,6 +455,8 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lvlData.IsBeaconActive = beaconActive;
|
||||||
|
|
||||||
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
|
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -712,7 +717,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
XElement petsElement = new XElement("pets");
|
petsElement = new XElement("pets");
|
||||||
PetBehavior.SavePets(petsElement);
|
PetBehavior.SavePets(petsElement);
|
||||||
modeElement.Add(petsElement);
|
modeElement.Add(petsElement);
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -121,7 +121,7 @@ namespace Barotrauma.Tutorials
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
character = Character.Create(charInfo, wayPoint.WorldPosition, "", false, false);
|
character = Character.Create(charInfo, wayPoint.WorldPosition, "", isRemotePlayer: false, hasAi: false);
|
||||||
character.TeamID = Character.TeamType.Team1;
|
character.TeamID = Character.TeamType.Team1;
|
||||||
Character.Controlled = character;
|
Character.Controlled = character;
|
||||||
character.GiveJobItems(null);
|
character.GiveJobItems(null);
|
||||||
|
|||||||
@@ -0,0 +1,266 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Barotrauma.Networking;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
internal partial class ReadyCheck
|
||||||
|
{
|
||||||
|
private static string readyCheckBody(string name) => string.IsNullOrWhiteSpace(name) ? TextManager.Get("readycheck.serverbody") : TextManager.GetWithVariable("readycheck.body", "[player]", name);
|
||||||
|
|
||||||
|
private static string readyCheckStatus(int ready, int total) => TextManager.GetWithVariables("readycheck.readycount", new[] { "[ready]", "[total]" }, new[] { ready.ToString(), total.ToString() });
|
||||||
|
private static string readyCheckPleaseWait(int seconds) => TextManager.GetWithVariable("readycheck.pleasewait", "[seconds]", seconds.ToString());
|
||||||
|
|
||||||
|
private static readonly string readyCheckHeader = TextManager.Get("ReadyCheck.Title");
|
||||||
|
|
||||||
|
private static readonly string noButton = TextManager.Get("No"),
|
||||||
|
yesButton = TextManager.Get("Yes"),
|
||||||
|
closeButton = TextManager.Get("Close");
|
||||||
|
|
||||||
|
private const string TimerData = "Timer",
|
||||||
|
PromptData = "ReadyCheck",
|
||||||
|
ResultData = "ReadyCheckResults",
|
||||||
|
UserListData = "ReadyUserList",
|
||||||
|
ReadySpriteData = "ReadySprite";
|
||||||
|
|
||||||
|
private int lastSecond;
|
||||||
|
|
||||||
|
private GUIMessageBox? msgBox;
|
||||||
|
private GUIMessageBox? resultsBox;
|
||||||
|
|
||||||
|
public static DateTime lastReadyCheck = DateTime.MinValue;
|
||||||
|
|
||||||
|
private void CreateMessageBox(string author)
|
||||||
|
{
|
||||||
|
Vector2 relativeSize = new Vector2(GUI.IsFourByThree() ? 0.3f : 0.2f, 0.15f);
|
||||||
|
Point minSize = new Point(300, 200);
|
||||||
|
msgBox = new GUIMessageBox(readyCheckHeader, readyCheckBody(author), new[] { yesButton, noButton }, relativeSize, minSize, type: GUIMessageBox.Type.Vote) { UserData = PromptData, Draggable = true };
|
||||||
|
|
||||||
|
GUILayoutGroup contentLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.125f), msgBox.Content.RectTransform), childAnchor: Anchor.Center);
|
||||||
|
new GUIProgressBar(new RectTransform(new Vector2(0.8f, 1f), contentLayout.RectTransform), time / endTime, GUI.Style.Orange) { UserData = TimerData };
|
||||||
|
|
||||||
|
// Yes
|
||||||
|
msgBox.Buttons[0].OnClicked = delegate
|
||||||
|
{
|
||||||
|
msgBox.Close();
|
||||||
|
SendState(ReadyStatus.Yes);
|
||||||
|
CreateResultsMessage();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// No
|
||||||
|
msgBox.Buttons[1].OnClicked = delegate
|
||||||
|
{
|
||||||
|
msgBox.Close();
|
||||||
|
SendState(ReadyStatus.No);
|
||||||
|
CreateResultsMessage();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateResultsMessage()
|
||||||
|
{
|
||||||
|
Vector2 relativeSize = new Vector2(0.2f, 0.3f);
|
||||||
|
Point minSize = new Point(300, 400);
|
||||||
|
resultsBox = new GUIMessageBox(readyCheckHeader, string.Empty, new[] { closeButton }, relativeSize, minSize, type: GUIMessageBox.Type.Vote) { UserData = ResultData, Draggable = true };
|
||||||
|
if (msgBox != null)
|
||||||
|
{
|
||||||
|
resultsBox.RectTransform.ScreenSpaceOffset = msgBox.RectTransform.ScreenSpaceOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
GUIListBox listBox = new GUIListBox(new RectTransform(new Vector2(1f, 0.8f), resultsBox.Content.RectTransform)) { UserData = UserListData };
|
||||||
|
|
||||||
|
foreach (var (id, status) in Clients)
|
||||||
|
{
|
||||||
|
Client? client = GameMain.Client.ConnectedClients.FirstOrDefault(c => c.ID == id);
|
||||||
|
GUIFrame container = new GUIFrame(new RectTransform(new Vector2(1f, 0.15f), listBox.Content.RectTransform), style: "ListBoxElement") { UserData = id };
|
||||||
|
GUILayoutGroup frame = new GUILayoutGroup(new RectTransform(Vector2.One, container.RectTransform), isHorizontal: true) { Stretch = true };
|
||||||
|
|
||||||
|
int height = frame.Rect.Height;
|
||||||
|
|
||||||
|
JobPrefab? jobPrefab = client?.Character?.Info?.Job?.Prefab;
|
||||||
|
|
||||||
|
if (client == null)
|
||||||
|
{
|
||||||
|
string list = GameMain.Client.ConnectedClients.Aggregate("Available clients:\n", (current, c) => current + $"{c.ID}: {c.Name}\n");
|
||||||
|
DebugConsole.ThrowError($"Client ID {id} was reported in ready check but was not found.\n" + list.TrimEnd('\n'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jobPrefab?.Icon != null)
|
||||||
|
{
|
||||||
|
// job icon
|
||||||
|
new GUIImage(new RectTransform(new Point(height, height), frame.RectTransform), jobPrefab.Icon, scaleToFit: true) { Color = jobPrefab.UIColor };
|
||||||
|
}
|
||||||
|
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(0.75f, 1), frame.RectTransform), client?.Name ?? $"Unknown ID {id}", jobPrefab?.UIColor ?? Color.White, textAlignment: Alignment.Center) { AutoScaleHorizontal = true };
|
||||||
|
new GUIImage(new RectTransform(new Point(height, height), frame.RectTransform), null, scaleToFit: true) { UserData = ReadySpriteData };
|
||||||
|
}
|
||||||
|
|
||||||
|
resultsBox.Buttons[0].OnClicked = delegate
|
||||||
|
{
|
||||||
|
resultsBox.Close();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateBar()
|
||||||
|
{
|
||||||
|
if (msgBox != null && !msgBox.Closed && GUIMessageBox.MessageBoxes.Contains(msgBox))
|
||||||
|
{
|
||||||
|
if (msgBox.FindChild(TimerData, true) is GUIProgressBar bar)
|
||||||
|
{
|
||||||
|
bar.BarSize = time / endTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// play click sound after a second has passed
|
||||||
|
int second = (int) Math.Ceiling(time);
|
||||||
|
if (second < lastSecond)
|
||||||
|
{
|
||||||
|
SoundPlayer.PlayUISound(GUISoundType.PopupMenu);
|
||||||
|
lastSecond = second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ClientRead(IReadMessage inc)
|
||||||
|
{
|
||||||
|
ReadyCheckState state = (ReadyCheckState) inc.ReadByte();
|
||||||
|
CrewManager? crewManager = GameMain.GameSession?.CrewManager;
|
||||||
|
List<Client> otherClients = GameMain.Client.ConnectedClients;
|
||||||
|
if (crewManager == null || otherClients == null) { return; }
|
||||||
|
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case ReadyCheckState.Start:
|
||||||
|
bool isOwn = false;
|
||||||
|
|
||||||
|
float duration = inc.ReadSingle();
|
||||||
|
string author = inc.ReadString();
|
||||||
|
bool hasAuthor = inc.ReadBoolean();
|
||||||
|
|
||||||
|
if (hasAuthor)
|
||||||
|
{
|
||||||
|
isOwn = inc.ReadByte() == GameMain.Client.ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
ushort clientCount = inc.ReadUInt16();
|
||||||
|
List<byte> clients = new List<byte>();
|
||||||
|
for (int i = 0; i < clientCount; i++)
|
||||||
|
{
|
||||||
|
clients.Add(inc.ReadByte());
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadyCheck rCheck = new ReadyCheck(clients, duration);
|
||||||
|
crewManager.ActiveReadyCheck = rCheck;
|
||||||
|
|
||||||
|
if (isOwn)
|
||||||
|
{
|
||||||
|
SendState(ReadyStatus.Yes);
|
||||||
|
rCheck.CreateResultsMessage();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rCheck.CreateMessageBox(author);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ReadyCheckState.Update:
|
||||||
|
crewManager.ActiveReadyCheck.time = inc.ReadSingle();
|
||||||
|
ReadyStatus newState = (ReadyStatus) inc.ReadByte();
|
||||||
|
byte targetId = inc.ReadByte();
|
||||||
|
crewManager.ActiveReadyCheck?.UpdateState(targetId, newState);
|
||||||
|
break;
|
||||||
|
case ReadyCheckState.End:
|
||||||
|
ushort count = inc.ReadUInt16();
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
byte id = inc.ReadByte();
|
||||||
|
ReadyStatus status = (ReadyStatus) inc.ReadByte();
|
||||||
|
crewManager.ActiveReadyCheck?.UpdateState(id, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
crewManager.ActiveReadyCheck?.EndReadyCheck();
|
||||||
|
crewManager.ActiveReadyCheck?.msgBox?.Close();
|
||||||
|
crewManager.ActiveReadyCheck = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
partial void EndReadyCheck()
|
||||||
|
{
|
||||||
|
int readyCount = Clients.Count(pair => pair.Value == ReadyStatus.Yes);
|
||||||
|
int totalCount = Clients.Count;
|
||||||
|
GameMain.Client.AddChatMessage(ChatMessage.Create(string.Empty, readyCheckStatus(readyCount, totalCount), ChatMessageType.Server, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateState(byte id, ReadyStatus status)
|
||||||
|
{
|
||||||
|
if (Clients.ContainsKey(id))
|
||||||
|
{
|
||||||
|
Clients[id] = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resultsBox == null || resultsBox.Closed || !GUIMessageBox.MessageBoxes.Contains(resultsBox)) { return; }
|
||||||
|
|
||||||
|
if (resultsBox.Content.FindChild(UserListData) is GUIListBox userList)
|
||||||
|
{
|
||||||
|
// for some reason FindChild doesn't work here?
|
||||||
|
foreach (GUIComponent child in userList.Content.Children)
|
||||||
|
{
|
||||||
|
if (!(child.UserData is byte b) || b != id) { continue; }
|
||||||
|
|
||||||
|
if (child.GetChild<GUILayoutGroup>().FindChild(ReadySpriteData) is GUIImage image)
|
||||||
|
{
|
||||||
|
string style;
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case ReadyStatus.Yes:
|
||||||
|
style = "MissionCompletedIcon";
|
||||||
|
break;
|
||||||
|
case ReadyStatus.No:
|
||||||
|
style = "MissionFailedIcon";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
image.ApplyStyle(GUI.Style.GetComponentStyle(style));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SendState(ReadyStatus status)
|
||||||
|
{
|
||||||
|
IWriteMessage msg = new WriteOnlyMessage();
|
||||||
|
msg.Write((byte) ClientPacketHeader.READY_CHECK);
|
||||||
|
msg.Write((byte) ReadyCheckState.Update);
|
||||||
|
msg.Write((byte) status);
|
||||||
|
GameMain.Client?.ClientPeer?.Send(msg, DeliveryMethod.Reliable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CreateReadyCheck()
|
||||||
|
{
|
||||||
|
if (lastReadyCheck < DateTime.Now)
|
||||||
|
{
|
||||||
|
#if !DEBUG
|
||||||
|
lastReadyCheck = DateTime.Now.AddMinutes(1);
|
||||||
|
#endif
|
||||||
|
IWriteMessage msg = new WriteOnlyMessage();
|
||||||
|
msg.Write((byte) ClientPacketHeader.READY_CHECK);
|
||||||
|
msg.Write((byte) ReadyCheckState.Start);
|
||||||
|
GameMain.Client?.ClientPeer?.Send(msg, DeliveryMethod.Reliable);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GUIMessageBox msgBox = new GUIMessageBox(readyCheckHeader, readyCheckPleaseWait((lastReadyCheck - DateTime.Now).Seconds), new[] { closeButton });
|
||||||
|
msgBox.Buttons[0].OnClicked = delegate
|
||||||
|
{
|
||||||
|
msgBox.Close();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1335,7 +1335,7 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
msgBox.Buttons[0].OnClicked = (yesButton, obj) =>
|
msgBox.Buttons[0].OnClicked = (yesButton, obj) =>
|
||||||
{
|
{
|
||||||
LoadDefaultConfig(setLanguage: false);
|
LoadDefaultConfig(setLanguage: false, loadContentPackages: Screen.Selected != GameMain.GameScreen);
|
||||||
CheckBindings(true);
|
CheckBindings(true);
|
||||||
RefreshItemMessages();
|
RefreshItemMessages();
|
||||||
ApplySettings();
|
ApplySettings();
|
||||||
|
|||||||
@@ -291,6 +291,7 @@ namespace Barotrauma.Items.Components
|
|||||||
bool broken = msg.ReadBoolean();
|
bool broken = msg.ReadBoolean();
|
||||||
bool forcedOpen = msg.ReadBoolean();
|
bool forcedOpen = msg.ReadBoolean();
|
||||||
bool isStuck = msg.ReadBoolean();
|
bool isStuck = msg.ReadBoolean();
|
||||||
|
bool isJammed = msg.ReadBoolean();
|
||||||
SetState(open, isNetworkMessage: true, sendNetworkMessage: false, forcedOpen: forcedOpen);
|
SetState(open, isNetworkMessage: true, sendNetworkMessage: false, forcedOpen: forcedOpen);
|
||||||
stuck = msg.ReadRangedSingle(0.0f, 100.0f, 8);
|
stuck = msg.ReadRangedSingle(0.0f, 100.0f, 8);
|
||||||
UInt16 lastUserID = msg.ReadUInt16();
|
UInt16 lastUserID = msg.ReadUInt16();
|
||||||
@@ -301,6 +302,7 @@ namespace Barotrauma.Items.Components
|
|||||||
toggleCooldownTimer = ToggleCoolDown;
|
toggleCooldownTimer = ToggleCoolDown;
|
||||||
}
|
}
|
||||||
this.isStuck = isStuck;
|
this.isStuck = isStuck;
|
||||||
|
this.isJammed = isJammed;
|
||||||
if (isStuck) { OpenState = 0.0f; }
|
if (isStuck) { OpenState = 0.0f; }
|
||||||
IsBroken = broken;
|
IsBroken = broken;
|
||||||
PredictedState = null;
|
PredictedState = null;
|
||||||
|
|||||||
@@ -8,46 +8,6 @@ using Microsoft.Xna.Framework.Graphics;
|
|||||||
|
|
||||||
namespace Barotrauma.Items.Components
|
namespace Barotrauma.Items.Components
|
||||||
{
|
{
|
||||||
internal partial class VineTile
|
|
||||||
{
|
|
||||||
public void Draw(SpriteBatch spriteBatch, Vector2 position, float depth, float leafDepth)
|
|
||||||
{
|
|
||||||
Vector2 pos = position + Position;
|
|
||||||
pos.Y = -pos.Y;
|
|
||||||
|
|
||||||
VineSprite vineSprite = Parent.VineSprites[Type];
|
|
||||||
Color color = Parent.Decayed ? Parent.DeadTint : Parent.VineTint;
|
|
||||||
|
|
||||||
float layer1 = depth + 0.01f, // flowers
|
|
||||||
layer2 = depth + 0.02f, // decay atlas
|
|
||||||
layer3 = depth + 0.03f; // branches and leaves
|
|
||||||
|
|
||||||
float scale = Parent.VineScale * VineStep;
|
|
||||||
|
|
||||||
if (Parent.VineAtlas != null)
|
|
||||||
{
|
|
||||||
spriteBatch.Draw(Parent.VineAtlas.Texture, pos + offset, vineSprite.SourceRect, color, 0f, vineSprite.AbsoluteOrigin, scale, SpriteEffects.None, layer3);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Parent.DecayAtlas != null)
|
|
||||||
{
|
|
||||||
spriteBatch.Draw(Parent.DecayAtlas.Texture, pos, vineSprite.SourceRect, HealthColor, 0f, vineSprite.AbsoluteOrigin, scale, SpriteEffects.None, layer2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FlowerConfig.Variant >= 0 && !Parent.Decayed)
|
|
||||||
{
|
|
||||||
Sprite flowerSprite = Parent.FlowerSprites[FlowerConfig.Variant];
|
|
||||||
flowerSprite.Draw(spriteBatch, pos, Parent.FlowerTint, flowerSprite.Origin, scale: Parent.BaseFlowerScale * FlowerConfig.Scale * FlowerStep, rotate: FlowerConfig.Rotation, depth: layer1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LeafConfig.Variant >= 0)
|
|
||||||
{
|
|
||||||
Sprite leafSprite = Parent.LeafSprites[LeafConfig.Variant];
|
|
||||||
leafSprite.Draw(spriteBatch, pos, Parent.Decayed ? Parent.DeadTint : Parent.LeafTint, leafSprite.Origin, scale: Parent.BaseLeafScale * LeafConfig.Scale * FlowerStep, rotate: LeafConfig.Rotation, depth: layer3 + leafDepth);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class VineSprite
|
internal class VineSprite
|
||||||
{
|
{
|
||||||
[Serialize("0,0,0,0", false)]
|
[Serialize("0,0,0,0", false)]
|
||||||
@@ -97,7 +57,7 @@ namespace Barotrauma.Items.Components
|
|||||||
foreach (VineTile vine in Vines)
|
foreach (VineTile vine in Vines)
|
||||||
{
|
{
|
||||||
leafDepth += zStep;
|
leafDepth += zStep;
|
||||||
vine.Draw(spriteBatch, planter.Item.DrawPosition + offset, depth, leafDepth);
|
DrawBranch(vine, spriteBatch, planter.Item.DrawPosition + offset, depth, leafDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameMain.DebugDraw)
|
if (GameMain.DebugDraw)
|
||||||
@@ -112,6 +72,43 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DrawBranch(VineTile vine, SpriteBatch spriteBatch, Vector2 position, float depth, float leafDepth)
|
||||||
|
{
|
||||||
|
Vector2 pos = position + vine.Position;
|
||||||
|
pos.Y = -pos.Y;
|
||||||
|
|
||||||
|
VineSprite vineSprite = VineSprites[vine.Type];
|
||||||
|
Color color = Decayed ? DeadTint : VineTint;
|
||||||
|
|
||||||
|
float layer1 = depth + 0.01f, // flowers
|
||||||
|
layer2 = depth + 0.02f, // decay atlas
|
||||||
|
layer3 = depth + 0.03f; // branches and leaves
|
||||||
|
|
||||||
|
float scale = VineScale * vine.VineStep;
|
||||||
|
|
||||||
|
if (VineAtlas != null)
|
||||||
|
{
|
||||||
|
spriteBatch.Draw(VineAtlas.Texture, pos + vine.offset, vineSprite.SourceRect, color, 0f, vineSprite.AbsoluteOrigin, scale, SpriteEffects.None, layer3);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DecayAtlas != null)
|
||||||
|
{
|
||||||
|
spriteBatch.Draw(DecayAtlas.Texture, pos, vineSprite.SourceRect, vine.HealthColor, 0f, vineSprite.AbsoluteOrigin, scale, SpriteEffects.None, layer2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vine.FlowerConfig.Variant >= 0 && !Decayed)
|
||||||
|
{
|
||||||
|
Sprite flowerSprite = FlowerSprites[vine.FlowerConfig.Variant];
|
||||||
|
flowerSprite.Draw(spriteBatch, pos, FlowerTint, flowerSprite.Origin, scale: BaseFlowerScale * vine.FlowerConfig.Scale * vine.FlowerStep, rotate: vine.FlowerConfig.Rotation, depth: layer1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vine.LeafConfig.Variant >= 0)
|
||||||
|
{
|
||||||
|
Sprite leafSprite = LeafSprites[vine.LeafConfig.Variant];
|
||||||
|
leafSprite.Draw(spriteBatch, pos, Decayed ? DeadTint : LeafTint, leafSprite.Origin, scale: BaseLeafScale * vine.LeafConfig.Scale * vine.FlowerStep, rotate: vine.LeafConfig.Rotation, depth: layer3 + leafDepth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
partial void LoadVines(XElement element)
|
partial void LoadVines(XElement element)
|
||||||
{
|
{
|
||||||
string? vineAtlasPath = element.GetAttributeString("vineatlas", null);
|
string? vineAtlasPath = element.GetAttributeString("vineatlas", null);
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Barotrauma.Items.Components
|
||||||
|
{
|
||||||
|
partial class IdCard
|
||||||
|
{
|
||||||
|
public Sprite StoredPortrait;
|
||||||
|
public Vector2 StoredSheetIndex;
|
||||||
|
public JobPrefab StoredJobPrefab;
|
||||||
|
public List<WearableSprite> StoredAttachments;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -257,6 +257,8 @@ namespace Barotrauma.Items.Components
|
|||||||
spriteEffects |= MathUtils.NearlyEqual(ItemRotation % 180, 90.0f) ? SpriteEffects.FlipHorizontally : SpriteEffects.FlipVertically;
|
spriteEffects |= MathUtils.NearlyEqual(ItemRotation % 180, 90.0f) ? SpriteEffects.FlipHorizontally : SpriteEffects.FlipVertically;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isWiringMode = SubEditorScreen.IsWiringMode();
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (Item containedItem in Inventory.Items)
|
foreach (Item containedItem in Inventory.Items)
|
||||||
{
|
{
|
||||||
@@ -278,7 +280,7 @@ namespace Barotrauma.Items.Components
|
|||||||
containedItem.Sprite.Draw(
|
containedItem.Sprite.Draw(
|
||||||
spriteBatch,
|
spriteBatch,
|
||||||
new Vector2(currentItemPos.X, -currentItemPos.Y),
|
new Vector2(currentItemPos.X, -currentItemPos.Y),
|
||||||
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 + MathHelper.ToRadians(-item.Rotation)),
|
||||||
containedItem.Scale,
|
containedItem.Scale,
|
||||||
|
|||||||
+8
-10
@@ -95,23 +95,21 @@ namespace Barotrauma.Items.Components
|
|||||||
// TODO, This works fine as of now but if GUI.PreventElementOverlap ever gets fixed this block of code may become obsolete or detrimental.
|
// TODO, This works fine as of now but if GUI.PreventElementOverlap ever gets fixed this block of code may become obsolete or detrimental.
|
||||||
// Only do this if there's only one linked component. If you link more containers then may
|
// Only do this if there's only one linked component. If you link more containers then may
|
||||||
// GUI.PreventElementOverlap have mercy on your HUD layout
|
// GUI.PreventElementOverlap have mercy on your HUD layout
|
||||||
if (item.linkedTo.Count(entity => entity is Item item && item.DisplaySideBySideWhenLinked) == 1)
|
if (GuiFrame != null && item.linkedTo.Count(entity => entity is Item item && item.DisplaySideBySideWhenLinked) == 1)
|
||||||
{
|
{
|
||||||
foreach (MapEntity linkedTo in item.linkedTo)
|
foreach (MapEntity linkedTo in item.linkedTo)
|
||||||
{
|
{
|
||||||
if (!(linkedTo is Item linkedItem)) continue;
|
if (!(linkedTo is Item linkedItem) || !linkedItem.DisplaySideBySideWhenLinked) { continue; }
|
||||||
if (!linkedItem.Components.Any()) continue;
|
if (!linkedItem.Components.Any()) { continue; }
|
||||||
|
|
||||||
var itemContainer = linkedItem.Components.First();
|
var itemContainer = linkedItem.GetComponent<ItemContainer>();
|
||||||
if (itemContainer == null) { continue; }
|
if (itemContainer?.GuiFrame == null || itemContainer.AllowUIOverlap) { continue; }
|
||||||
|
|
||||||
if (!itemContainer.Item.DisplaySideBySideWhenLinked) continue;
|
|
||||||
|
|
||||||
// how much spacing do we want between the components
|
// how much spacing do we want between the components
|
||||||
var padding = (int) (8 * GUI.Scale);
|
var padding = (int) (8 * GUI.Scale);
|
||||||
// Move the linked container to the right and move the fabricator to the left
|
// Move the linked container to the right and move the deconstructor to the left
|
||||||
itemContainer.GuiFrame.RectTransform.AbsoluteOffset = new Point(GuiFrame.Rect.Width / -2 - padding, 0);
|
itemContainer.GuiFrame.RectTransform.AbsoluteOffset = new Point(100, 0);
|
||||||
GuiFrame.RectTransform.AbsoluteOffset = new Point(itemContainer.GuiFrame.Rect.Width / 2 + padding, 0);
|
GuiFrame.RectTransform.AbsoluteOffset = new Point(-100, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return base.Select(character);
|
return base.Select(character);
|
||||||
|
|||||||
@@ -212,23 +212,21 @@ namespace Barotrauma.Items.Components
|
|||||||
// TODO, This works fine as of now but if GUI.PreventElementOverlap ever gets fixed this block of code may become obsolete or detrimental.
|
// TODO, This works fine as of now but if GUI.PreventElementOverlap ever gets fixed this block of code may become obsolete or detrimental.
|
||||||
// Only do this if there's only one linked component. If you link more containers then may
|
// Only do this if there's only one linked component. If you link more containers then may
|
||||||
// GUI.PreventElementOverlap have mercy on your HUD layout
|
// GUI.PreventElementOverlap have mercy on your HUD layout
|
||||||
if (item.linkedTo.Count(entity => entity is Item item && item.DisplaySideBySideWhenLinked) == 1)
|
if (GuiFrame != null && item.linkedTo.Count(entity => entity is Item item && item.DisplaySideBySideWhenLinked) == 1)
|
||||||
{
|
{
|
||||||
foreach (MapEntity linkedTo in item.linkedTo)
|
foreach (MapEntity linkedTo in item.linkedTo)
|
||||||
{
|
{
|
||||||
if (!(linkedTo is Item linkedItem)) continue;
|
if (!(linkedTo is Item linkedItem) || !linkedItem.DisplaySideBySideWhenLinked) { continue; }
|
||||||
if (!linkedItem.Components.Any()) continue;
|
if (!linkedItem.Components.Any()) { continue; }
|
||||||
|
|
||||||
var itemContainer = linkedItem.Components.First();
|
var itemContainer = linkedItem.GetComponent<ItemContainer>();
|
||||||
if (itemContainer == null) { continue; }
|
if (itemContainer?.GuiFrame == null || itemContainer.AllowUIOverlap) { continue; }
|
||||||
|
|
||||||
if (!itemContainer.Item.DisplaySideBySideWhenLinked) continue;
|
|
||||||
|
|
||||||
// how much spacing do we want between the components
|
// how much spacing do we want between the components
|
||||||
var padding = (int) (8 * GUI.Scale);
|
var padding = (int) (8 * GUI.Scale);
|
||||||
// Move the linked container to the right and move the fabricator to the left
|
// Move the linked container to the right and move the fabricator to the left
|
||||||
itemContainer.GuiFrame.RectTransform.AbsoluteOffset = new Point(GuiFrame.Rect.Width / -2 - padding, 0);
|
itemContainer.GuiFrame.RectTransform.AbsoluteOffset = new Point(-100, 0);
|
||||||
GuiFrame.RectTransform.AbsoluteOffset = new Point(itemContainer.GuiFrame.Rect.Width / 2 + padding, 0);
|
GuiFrame.RectTransform.AbsoluteOffset = new Point(100, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
OnClicked = (button, data) =>
|
OnClicked = (button, data) =>
|
||||||
{
|
{
|
||||||
targetLevel = null;
|
TargetLevel = null;
|
||||||
IsActive = !IsActive;
|
IsActive = !IsActive;
|
||||||
if (GameMain.Client != null)
|
if (GameMain.Client != null)
|
||||||
{
|
{
|
||||||
@@ -112,7 +112,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
if (pumpSpeedLockTimer <= 0.0f)
|
if (pumpSpeedLockTimer <= 0.0f)
|
||||||
{
|
{
|
||||||
targetLevel = null;
|
TargetLevel = null;
|
||||||
}
|
}
|
||||||
float newValue = barScroll * 200.0f - 100.0f;
|
float newValue = barScroll * 200.0f - 100.0f;
|
||||||
if (Math.Abs(newValue - FlowPercentage) < 0.1f) { return false; }
|
if (Math.Abs(newValue - FlowPercentage) < 0.1f) { return false; }
|
||||||
@@ -223,6 +223,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
FlowPercentage = msg.ReadRangedInteger(-10, 10) * 10.0f;
|
FlowPercentage = msg.ReadRangedInteger(-10, 10) * 10.0f;
|
||||||
IsActive = msg.ReadBoolean();
|
IsActive = msg.ReadBoolean();
|
||||||
|
Hijacked = msg.ReadBoolean();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Barotrauma.Networking;
|
using Barotrauma.Extensions;
|
||||||
|
using Barotrauma.Networking;
|
||||||
using FarseerPhysics;
|
using FarseerPhysics;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
@@ -28,11 +29,18 @@ namespace Barotrauma.Items.Components
|
|||||||
private GUITickBox activeTickBox, passiveTickBox;
|
private GUITickBox activeTickBox, passiveTickBox;
|
||||||
private GUITextBlock signalWarningText;
|
private GUITextBlock signalWarningText;
|
||||||
|
|
||||||
|
private GUIFrame lowerAreaFrame;
|
||||||
|
|
||||||
private GUIScrollBar zoomSlider;
|
private GUIScrollBar zoomSlider;
|
||||||
|
|
||||||
private GUIButton directionalModeSwitch;
|
private GUIButton directionalModeSwitch;
|
||||||
private Vector2? pingDragDirection = null;
|
private Vector2? pingDragDirection = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Can be null if the property HasMineralScanner is false
|
||||||
|
/// </summary>
|
||||||
|
private GUIButton mineralScannerSwitch;
|
||||||
|
|
||||||
private GUIFrame controlContainer;
|
private GUIFrame controlContainer;
|
||||||
|
|
||||||
private GUICustomComponent sonarView;
|
private GUICustomComponent sonarView;
|
||||||
@@ -60,8 +68,6 @@ namespace Barotrauma.Items.Components
|
|||||||
private const float DisruptionUpdateInterval = 0.2f;
|
private const float DisruptionUpdateInterval = 0.2f;
|
||||||
private float disruptionUpdateTimer;
|
private float disruptionUpdateTimer;
|
||||||
|
|
||||||
private float zoomSqrt;
|
|
||||||
|
|
||||||
private float showDirectionalIndicatorTimer;
|
private float showDirectionalIndicatorTimer;
|
||||||
|
|
||||||
//Vector2 = vector from the ping source to the position of the disruption
|
//Vector2 = vector from the ping source to the position of the disruption
|
||||||
@@ -114,6 +120,10 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
public static Vector2 GUISizeCalculation => Vector2.One * Math.Min(GUI.RelativeHorizontalAspectRatio, 1f) * sonarAreaSize;
|
public static Vector2 GUISizeCalculation => Vector2.One * Math.Min(GUI.RelativeHorizontalAspectRatio, 1f) * sonarAreaSize;
|
||||||
|
|
||||||
|
private List<Tuple<Vector2, List<Item>>> MineralClusters { get; set; }
|
||||||
|
|
||||||
|
private readonly List<GUITextBlock> textBlocksToScaleAndNormalize = new List<GUITextBlock>();
|
||||||
|
|
||||||
partial void InitProjSpecific(XElement element)
|
partial void InitProjSpecific(XElement element)
|
||||||
{
|
{
|
||||||
System.Diagnostics.Debug.Assert(Enum.GetValues(typeof(BlipType)).Cast<BlipType>().All(t => blipColorGradient.ContainsKey(t)));
|
System.Diagnostics.Debug.Assert(Enum.GetValues(typeof(BlipType)).Cast<BlipType>().All(t => blipColorGradient.ContainsKey(t)));
|
||||||
@@ -214,11 +224,14 @@ namespace Barotrauma.Items.Components
|
|||||||
};
|
};
|
||||||
passiveTickBox.TextBlock.OverrideTextColor(GUI.Style.TextColor);
|
passiveTickBox.TextBlock.OverrideTextColor(GUI.Style.TextColor);
|
||||||
activeTickBox.TextBlock.OverrideTextColor(GUI.Style.TextColor);
|
activeTickBox.TextBlock.OverrideTextColor(GUI.Style.TextColor);
|
||||||
|
textBlocksToScaleAndNormalize.Add(passiveTickBox.TextBlock);
|
||||||
|
textBlocksToScaleAndNormalize.Add(activeTickBox.TextBlock);
|
||||||
|
|
||||||
var lowerArea = new GUIFrame(new RectTransform(new Vector2(1, 0.4f + extraHeight), paddedControlContainer.RectTransform, Anchor.BottomCenter), style: null);
|
lowerAreaFrame = new GUIFrame(new RectTransform(new Vector2(1, 0.4f + extraHeight), paddedControlContainer.RectTransform, Anchor.BottomCenter), style: null);
|
||||||
var zoomContainer = new GUIFrame(new RectTransform(new Vector2(1, 0.45f), lowerArea.RectTransform, Anchor.TopCenter), style: null);
|
var zoomContainer = new GUIFrame(new RectTransform(new Vector2(1, 0.45f), lowerAreaFrame.RectTransform, Anchor.TopCenter), style: null);
|
||||||
var zoomText = new GUITextBlock(new RectTransform(new Vector2(0.3f, 0.6f), zoomContainer.RectTransform, Anchor.CenterLeft),
|
var zoomText = new GUITextBlock(new RectTransform(new Vector2(0.3f, 0.6f), zoomContainer.RectTransform, Anchor.CenterLeft),
|
||||||
TextManager.Get("SonarZoom"), font: GUI.SubHeadingFont, textAlignment: Alignment.CenterRight);
|
TextManager.Get("SonarZoom"), font: GUI.SubHeadingFont, textAlignment: Alignment.CenterRight);
|
||||||
|
textBlocksToScaleAndNormalize.Add(zoomText);
|
||||||
zoomSlider = new GUIScrollBar(new RectTransform(new Vector2(0.5f, 0.8f), zoomContainer.RectTransform, Anchor.CenterLeft)
|
zoomSlider = new GUIScrollBar(new RectTransform(new Vector2(0.5f, 0.8f), zoomContainer.RectTransform, Anchor.CenterLeft)
|
||||||
{
|
{
|
||||||
RelativeOffset = new Vector2(0.35f, 0)
|
RelativeOffset = new Vector2(0.35f, 0)
|
||||||
@@ -238,7 +251,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
new GUIFrame(new RectTransform(new Vector2(0.8f, 0.01f), paddedControlContainer.RectTransform, Anchor.Center), style: "HorizontalLine");
|
new GUIFrame(new RectTransform(new Vector2(0.8f, 0.01f), paddedControlContainer.RectTransform, Anchor.Center), style: "HorizontalLine");
|
||||||
|
|
||||||
var directionalModeFrame = new GUIFrame(new RectTransform(new Vector2(1, 0.45f), lowerArea.RectTransform, Anchor.BottomCenter), style: null);
|
var directionalModeFrame = new GUIFrame(new RectTransform(new Vector2(1, 0.45f), lowerAreaFrame.RectTransform, Anchor.BottomCenter), style: null);
|
||||||
directionalModeSwitch = new GUIButton(new RectTransform(new Vector2(0.3f, 0.8f), directionalModeFrame.RectTransform, Anchor.CenterLeft), string.Empty, style: "SwitchHorizontal")
|
directionalModeSwitch = new GUIButton(new RectTransform(new Vector2(0.3f, 0.8f), directionalModeFrame.RectTransform, Anchor.CenterLeft), string.Empty, style: "SwitchHorizontal")
|
||||||
{
|
{
|
||||||
OnClicked = (button, data) =>
|
OnClicked = (button, data) =>
|
||||||
@@ -255,11 +268,11 @@ namespace Barotrauma.Items.Components
|
|||||||
};
|
};
|
||||||
var directionalModeSwitchText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1), directionalModeFrame.RectTransform, Anchor.CenterRight),
|
var directionalModeSwitchText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1), directionalModeFrame.RectTransform, Anchor.CenterRight),
|
||||||
TextManager.Get("SonarDirectionalPing"), GUI.Style.TextColor, GUI.SubHeadingFont, Alignment.CenterLeft);
|
TextManager.Get("SonarDirectionalPing"), GUI.Style.TextColor, GUI.SubHeadingFont, Alignment.CenterLeft);
|
||||||
|
textBlocksToScaleAndNormalize.Add(directionalModeSwitchText);
|
||||||
|
|
||||||
GuiFrame.CanBeFocused = false;
|
GuiFrame.CanBeFocused = false;
|
||||||
|
|
||||||
GUITextBlock.AutoScaleAndNormalize(passiveTickBox.TextBlock, activeTickBox.TextBlock, zoomText, directionalModeSwitchText);
|
GUITextBlock.AutoScaleAndNormalize(textBlocksToScaleAndNormalize);
|
||||||
|
|
||||||
sonarView = new GUICustomComponent(new RectTransform(Vector2.One * 0.7f, GuiFrame.RectTransform, Anchor.BottomRight, scaleBasis: ScaleBasis.BothHeight),
|
sonarView = new GUICustomComponent(new RectTransform(Vector2.One * 0.7f, GuiFrame.RectTransform, Anchor.BottomRight, scaleBasis: ScaleBasis.BothHeight),
|
||||||
(spriteBatch, guiCustomComponent) => { DrawSonar(spriteBatch, guiCustomComponent.Rect); }, null);
|
(spriteBatch, guiCustomComponent) => { DrawSonar(spriteBatch, guiCustomComponent.Rect); }, null);
|
||||||
@@ -275,7 +288,7 @@ namespace Barotrauma.Items.Components
|
|||||||
sonarView.RectTransform.ScaleBasis = ScaleBasis.Smallest;
|
sonarView.RectTransform.ScaleBasis = ScaleBasis.Smallest;
|
||||||
sonarView.RectTransform.SetPosition(Anchor.CenterRight);
|
sonarView.RectTransform.SetPosition(Anchor.CenterRight);
|
||||||
sonarView.RectTransform.Resize(GUISizeCalculation);
|
sonarView.RectTransform.Resize(GUISizeCalculation);
|
||||||
GUITextBlock.AutoScaleAndNormalize(passiveTickBox.TextBlock, activeTickBox.TextBlock, zoomText, directionalModeSwitchText);
|
GUITextBlock.AutoScaleAndNormalize(textBlocksToScaleAndNormalize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,10 +306,40 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
base.OnItemLoaded();
|
base.OnItemLoaded();
|
||||||
zoomSlider.BarScroll = MathUtils.InverseLerp(MinZoom, MaxZoom, zoom);
|
zoomSlider.BarScroll = MathUtils.InverseLerp(MinZoom, MaxZoom, zoom);
|
||||||
|
if (HasMineralScanner) { AddMineralScannerSwitchToGUI(); }
|
||||||
//make the sonarView customcomponent render the steering view so it gets drawn in front of the sonar
|
//make the sonarView customcomponent render the steering view so it gets drawn in front of the sonar
|
||||||
item.GetComponent<Steering>()?.AttachToSonarHUD(sonarView);
|
item.GetComponent<Steering>()?.AttachToSonarHUD(sonarView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AddMineralScannerSwitchToGUI()
|
||||||
|
{
|
||||||
|
// First adjust other elements of the lower area
|
||||||
|
zoomSlider.Parent.RectTransform.RelativeSize = new Vector2(1.0f, 0.3f);
|
||||||
|
directionalModeSwitch.Parent.RectTransform.RelativeSize = new Vector2(1.0f, 0.3f);
|
||||||
|
directionalModeSwitch.Parent.RectTransform.SetPosition(Anchor.Center);
|
||||||
|
|
||||||
|
// Then add the scanner switch
|
||||||
|
var mineralScannerFrame = new GUIFrame(new RectTransform(new Vector2(1, 0.3f), lowerAreaFrame.RectTransform, Anchor.BottomCenter), style: null);
|
||||||
|
mineralScannerSwitch = new GUIButton(new RectTransform(new Vector2(0.3f, 0.8f), mineralScannerFrame.RectTransform, Anchor.CenterLeft), string.Empty, style: "SwitchHorizontal")
|
||||||
|
{
|
||||||
|
OnClicked = (button, data) =>
|
||||||
|
{
|
||||||
|
useMineralScanner = !useMineralScanner;
|
||||||
|
button.Selected = useMineralScanner;
|
||||||
|
if (GameMain.Client != null)
|
||||||
|
{
|
||||||
|
unsentChanges = true;
|
||||||
|
correctionTimer = CorrectionDelay;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var mineralScannerSwitchText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1), mineralScannerFrame.RectTransform, Anchor.CenterRight),
|
||||||
|
TextManager.Get("SonarMineralScanner"), GUI.Style.TextColor, GUI.SubHeadingFont, Alignment.CenterLeft);
|
||||||
|
textBlocksToScaleAndNormalize.Add(mineralScannerSwitchText);
|
||||||
|
GUITextBlock.AutoScaleAndNormalize(textBlocksToScaleAndNormalize);
|
||||||
|
}
|
||||||
|
|
||||||
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
||||||
{
|
{
|
||||||
showDirectionalIndicatorTimer -= deltaTime;
|
showDirectionalIndicatorTimer -= deltaTime;
|
||||||
@@ -339,6 +382,32 @@ namespace Barotrauma.Items.Components
|
|||||||
Vector2.DistanceSquared(sonarView.Rect.Center.ToVector2(), PlayerInput.MousePosition) <
|
Vector2.DistanceSquared(sonarView.Rect.Center.ToVector2(), PlayerInput.MousePosition) <
|
||||||
(sonarView.Rect.Width / 2 * sonarView.Rect.Width / 2);
|
(sonarView.Rect.Width / 2 * sonarView.Rect.Width / 2);
|
||||||
|
|
||||||
|
if (HasMineralScanner && Level.Loaded != null && !Level.Loaded.Generating)
|
||||||
|
{
|
||||||
|
if (MineralClusters == null)
|
||||||
|
{
|
||||||
|
MineralClusters = new List<Tuple<Vector2, List<Item>>>();
|
||||||
|
foreach (var p in Level.Loaded.PathPoints)
|
||||||
|
{
|
||||||
|
foreach (var c in p.ClusterLocations)
|
||||||
|
{
|
||||||
|
if (c.Resources.None(i => i != null && !i.Removed && i.Tags.Contains("ore"))) { continue; }
|
||||||
|
var pos = Vector2.Zero;
|
||||||
|
foreach (var r in c.Resources)
|
||||||
|
{
|
||||||
|
pos += r.WorldPosition;
|
||||||
|
}
|
||||||
|
pos /= c.Resources.Count;
|
||||||
|
MineralClusters.Add(new Tuple<Vector2, List<Item>>(pos, c.Resources));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MineralClusters.RemoveAll(t => t.Item2 == null || t.Item2.None() || t.Item2.All(i => i == null || i.Removed));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (UseTransducers && connectedTransducers.Count == 0)
|
if (UseTransducers && connectedTransducers.Count == 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -348,12 +417,16 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (Level.Loaded != null)
|
if (Level.Loaded != null)
|
||||||
{
|
{
|
||||||
|
List<LevelTrigger> ballastFloraSpores = new List<LevelTrigger>();
|
||||||
Dictionary<LevelTrigger, Vector2> levelTriggerFlows = new Dictionary<LevelTrigger, Vector2>();
|
Dictionary<LevelTrigger, Vector2> levelTriggerFlows = new Dictionary<LevelTrigger, Vector2>();
|
||||||
for (var pingIndex = 0; pingIndex < activePingsCount; ++pingIndex)
|
for (var pingIndex = 0; pingIndex < activePingsCount; ++pingIndex)
|
||||||
{
|
{
|
||||||
var activePing = activePings[pingIndex];
|
var activePing = activePings[pingIndex];
|
||||||
foreach (LevelObject levelObject in Level.Loaded.LevelObjectManager.GetAllObjects(transducerCenter, range * activePing.State / zoom))
|
LevelObjectManager objManager = Level.Loaded.LevelObjectManager;
|
||||||
|
float pingRange = range * activePing.State / zoom;
|
||||||
|
foreach (LevelObject levelObject in objManager.GetAllObjects(transducerCenter, pingRange))
|
||||||
{
|
{
|
||||||
|
if (levelObject.Triggers == null) { continue; }
|
||||||
//gather all nearby triggers that are causing the water to flow into the dictionary
|
//gather all nearby triggers that are causing the water to flow into the dictionary
|
||||||
foreach (LevelTrigger trigger in levelObject.Triggers)
|
foreach (LevelTrigger trigger in levelObject.Triggers)
|
||||||
{
|
{
|
||||||
@@ -363,6 +436,10 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
levelTriggerFlows.Add(trigger, flow);
|
levelTriggerFlows.Add(trigger, flow);
|
||||||
}
|
}
|
||||||
|
if (!string.IsNullOrWhiteSpace(trigger.InfectIdentifier) && Vector2.DistanceSquared(transducerCenter, trigger.WorldPosition) < pingRange / 2 * pingRange / 2)
|
||||||
|
{
|
||||||
|
ballastFloraSpores.Add(trigger);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -400,6 +477,19 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (LevelTrigger spore in ballastFloraSpores)
|
||||||
|
{
|
||||||
|
Vector2 blipPos = spore.WorldPosition + Rand.Vector(spore.ColliderRadius * Rand.Range(0.0f, 1.0f));
|
||||||
|
SonarBlip sporeBlip = new SonarBlip(blipPos, Rand.Range(0.1f, 0.5f), 0.5f)
|
||||||
|
{
|
||||||
|
Rotation = Rand.Range(-MathHelper.TwoPi, MathHelper.TwoPi),
|
||||||
|
BlipType = BlipType.Default,
|
||||||
|
Velocity = Rand.Vector(100f, Rand.RandSync.Unsynced)
|
||||||
|
};
|
||||||
|
|
||||||
|
sonarBlips.Add(sporeBlip);
|
||||||
|
}
|
||||||
|
|
||||||
float outsideLevelFlow = 0.0f;
|
float outsideLevelFlow = 0.0f;
|
||||||
if (transducerCenter.X < 0.0f)
|
if (transducerCenter.X < 0.0f)
|
||||||
{
|
{
|
||||||
@@ -721,6 +811,24 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (HasMineralScanner && useMineralScanner && CurrentMode == Mode.Active && MineralClusters != null)
|
||||||
|
{
|
||||||
|
var maxMineralScanRangeSquared = Range * Range;
|
||||||
|
foreach (var t in MineralClusters)
|
||||||
|
{
|
||||||
|
var unobtainedMinerals = t.Item2.Where(i => i != null && i.GetRootInventoryOwner() == i);
|
||||||
|
if (unobtainedMinerals.None()) { continue; }
|
||||||
|
if (Vector2.DistanceSquared(transducerCenter, t.Item1) > maxMineralScanRangeSquared) { continue; }
|
||||||
|
var i = unobtainedMinerals.FirstOrDefault();
|
||||||
|
if (i == null) { continue; }
|
||||||
|
DrawMarker(spriteBatch,
|
||||||
|
i.Name, null, i,
|
||||||
|
t.Item1, transducerCenter,
|
||||||
|
displayScale, center, DisplayRadius * 0.95f,
|
||||||
|
onlyShowTextOnMouseOver: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (Submarine sub in Submarine.Loaded)
|
foreach (Submarine sub in Submarine.Loaded)
|
||||||
{
|
{
|
||||||
if (!sub.ShowSonarMarker) { continue; }
|
if (!sub.ShowSonarMarker) { continue; }
|
||||||
@@ -1334,7 +1442,8 @@ namespace Barotrauma.Items.Components
|
|||||||
sonarBlip.Draw(spriteBatch, center + pos, color * 0.5f, sonarBlip.Origin, 0, scale, SpriteEffects.None, 0);
|
sonarBlip.Draw(spriteBatch, center + pos, color * 0.5f, sonarBlip.Origin, 0, scale, SpriteEffects.None, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawMarker(SpriteBatch spriteBatch, string label, string iconIdentifier, object targetIdentifier, Vector2 worldPosition, Vector2 transducerPosition, float scale, Vector2 center, float radius)
|
private void DrawMarker(SpriteBatch spriteBatch, string label, string iconIdentifier, object targetIdentifier, Vector2 worldPosition, Vector2 transducerPosition, float scale, Vector2 center, float radius,
|
||||||
|
bool onlyShowTextOnMouseOver = false)
|
||||||
{
|
{
|
||||||
float linearDist = Vector2.Distance(worldPosition, transducerPosition);
|
float linearDist = Vector2.Distance(worldPosition, transducerPosition);
|
||||||
float dist = linearDist;
|
float dist = linearDist;
|
||||||
@@ -1391,16 +1500,27 @@ namespace Barotrauma.Items.Components
|
|||||||
markerPos.Y = (int)markerPos.Y;
|
markerPos.Y = (int)markerPos.Y;
|
||||||
|
|
||||||
float alpha = 1.0f;
|
float alpha = 1.0f;
|
||||||
if (linearDist * scale < radius)
|
if (!onlyShowTextOnMouseOver)
|
||||||
{
|
{
|
||||||
float normalizedDist = linearDist * scale / radius;
|
if (linearDist * scale < radius)
|
||||||
alpha = Math.Max(normalizedDist - 0.4f, 0.0f);
|
|
||||||
|
|
||||||
float mouseDist = Vector2.Distance(PlayerInput.MousePosition, markerPos);
|
|
||||||
float hoverThreshold = 150.0f;
|
|
||||||
if (mouseDist < hoverThreshold)
|
|
||||||
{
|
{
|
||||||
alpha += (hoverThreshold - mouseDist) / hoverThreshold;
|
float normalizedDist = linearDist * scale / radius;
|
||||||
|
alpha = Math.Max(normalizedDist - 0.4f, 0.0f);
|
||||||
|
|
||||||
|
float mouseDist = Vector2.Distance(PlayerInput.MousePosition, markerPos);
|
||||||
|
float hoverThreshold = 150.0f;
|
||||||
|
if (mouseDist < hoverThreshold)
|
||||||
|
{
|
||||||
|
alpha += (hoverThreshold - mouseDist) / hoverThreshold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float mouseDist = Vector2.Distance(PlayerInput.MousePosition, markerPos);
|
||||||
|
if (mouseDist > 5)
|
||||||
|
{
|
||||||
|
alpha = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1446,6 +1566,8 @@ namespace Barotrauma.Items.Components
|
|||||||
sprite.Remove();
|
sprite.Remove();
|
||||||
}
|
}
|
||||||
targetIcons.Clear();
|
targetIcons.Clear();
|
||||||
|
|
||||||
|
MineralClusters = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
||||||
@@ -1460,6 +1582,7 @@ namespace Barotrauma.Items.Components
|
|||||||
float pingAngle = MathUtils.WrapAngleTwoPi(MathUtils.VectorToAngle(pingDirection));
|
float pingAngle = MathUtils.WrapAngleTwoPi(MathUtils.VectorToAngle(pingDirection));
|
||||||
msg.WriteRangedSingle(MathUtils.InverseLerp(0.0f, MathHelper.TwoPi, pingAngle), 0.0f, 1.0f, 8);
|
msg.WriteRangedSingle(MathUtils.InverseLerp(0.0f, MathHelper.TwoPi, pingAngle), 0.0f, 1.0f, 8);
|
||||||
}
|
}
|
||||||
|
msg.Write(useMineralScanner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1471,6 +1594,7 @@ namespace Barotrauma.Items.Components
|
|||||||
float zoomT = 1.0f;
|
float zoomT = 1.0f;
|
||||||
bool directionalPing = useDirectionalPing;
|
bool directionalPing = useDirectionalPing;
|
||||||
float directionT = 0.0f;
|
float directionT = 0.0f;
|
||||||
|
bool mineralScanner = useMineralScanner;
|
||||||
if (isActive)
|
if (isActive)
|
||||||
{
|
{
|
||||||
zoomT = msg.ReadRangedSingle(0.0f, 1.0f, 8);
|
zoomT = msg.ReadRangedSingle(0.0f, 1.0f, 8);
|
||||||
@@ -1479,6 +1603,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
directionT = msg.ReadRangedSingle(0.0f, 1.0f, 8);
|
directionT = msg.ReadRangedSingle(0.0f, 1.0f, 8);
|
||||||
}
|
}
|
||||||
|
mineralScanner = msg.ReadBoolean();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (correctionTimer > 0.0f)
|
if (correctionTimer > 0.0f)
|
||||||
@@ -1500,6 +1625,11 @@ namespace Barotrauma.Items.Components
|
|||||||
pingDirection = new Vector2((float)Math.Cos(pingAngle), (float)Math.Sin(pingAngle));
|
pingDirection = new Vector2((float)Math.Cos(pingAngle), (float)Math.Sin(pingAngle));
|
||||||
}
|
}
|
||||||
useDirectionalPing = directionalModeSwitch.Selected = directionalPing;
|
useDirectionalPing = directionalModeSwitch.Selected = directionalPing;
|
||||||
|
useMineralScanner = mineralScanner;
|
||||||
|
if (mineralScannerSwitch != null)
|
||||||
|
{
|
||||||
|
mineralScannerSwitch.Selected = mineralScanner;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1510,6 +1640,10 @@ namespace Barotrauma.Items.Components
|
|||||||
passiveTickBox.Selected = !isActive;
|
passiveTickBox.Selected = !isActive;
|
||||||
activeTickBox.Selected = isActive;
|
activeTickBox.Selected = isActive;
|
||||||
directionalModeSwitch.Selected = useDirectionalPing;
|
directionalModeSwitch.Selected = useDirectionalPing;
|
||||||
|
if (mineralScannerSwitch != null)
|
||||||
|
{
|
||||||
|
mineralScannerSwitch.Selected = useMineralScanner;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -319,8 +319,7 @@ namespace Barotrauma.Items.Components
|
|||||||
centerText = $"({TextManager.Get("Meter")})";
|
centerText = $"({TextManager.Get("Meter")})";
|
||||||
rightTextGetter = () =>
|
rightTextGetter = () =>
|
||||||
{
|
{
|
||||||
Vector2 pos = controlledSub == null ? Vector2.Zero : controlledSub.Position;
|
float realWorldDepth = controlledSub == null ? -1000.0f : controlledSub.RealWorldDepth;
|
||||||
float realWorldDepth = Level.Loaded == null ? 0.0f : Math.Abs(pos.Y - Level.Loaded.Size.Y) * Physics.DisplayToRealWorldRatio;
|
|
||||||
return ((int)realWorldDepth).ToString();
|
return ((int)realWorldDepth).ToString();
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
using Barotrauma.Networking;
|
using Barotrauma.Networking;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Xml.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Barotrauma.Items.Components
|
namespace Barotrauma.Items.Components
|
||||||
{
|
{
|
||||||
@@ -10,6 +9,23 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
|
bool launch = msg.ReadBoolean();
|
||||||
|
if (launch)
|
||||||
|
{
|
||||||
|
ushort userId = msg.ReadUInt16();
|
||||||
|
User = Entity.FindEntityByID(userId) as Character;
|
||||||
|
Vector2 simPosition = new Vector2(msg.ReadSingle(), msg.ReadSingle());
|
||||||
|
float rotation = msg.ReadSingle();
|
||||||
|
if (User != null)
|
||||||
|
{
|
||||||
|
Shoot(User, simPosition, simPosition, rotation, ignoredBodies: User.AnimController.Limbs.Where(l => !l.IsSevered).Select(l => l.body.FarseerBody).ToList(), createNetworkEvent: false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Launch(User, simPosition, rotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool isStuck = msg.ReadBoolean();
|
bool isStuck = msg.ReadBoolean();
|
||||||
if (isStuck)
|
if (isStuck)
|
||||||
{
|
{
|
||||||
@@ -56,7 +72,15 @@ namespace Barotrauma.Items.Components
|
|||||||
else if (entity is Item item)
|
else if (entity is Item item)
|
||||||
{
|
{
|
||||||
if (item.Removed) { return; }
|
if (item.Removed) { return; }
|
||||||
StickToTarget(item.body.FarseerBody, axis);
|
var door = item.GetComponent<Door>();
|
||||||
|
if (door != null)
|
||||||
|
{
|
||||||
|
StickToTarget(door.Body.FarseerBody, axis);
|
||||||
|
}
|
||||||
|
else if (item.body != null)
|
||||||
|
{
|
||||||
|
StickToTarget(item.body.FarseerBody, axis);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (entity is Submarine sub)
|
else if (entity is Submarine sub)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using Barotrauma.Networking;
|
using Barotrauma.Networking;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
|
||||||
@@ -70,7 +69,13 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
partial void ShowOnDisplay(string input)
|
partial void ShowOnDisplay(string input)
|
||||||
{
|
{
|
||||||
while (historyBox.Content.CountChildren > 60)
|
messageHistory.Add(input);
|
||||||
|
while (messageHistory.Count > MaxMessages)
|
||||||
|
{
|
||||||
|
messageHistory.RemoveAt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (historyBox.Content.CountChildren > MaxMessages)
|
||||||
{
|
{
|
||||||
historyBox.RemoveChild(historyBox.Content.Children.First());
|
historyBox.RemoveChild(historyBox.Content.Children.First());
|
||||||
}
|
}
|
||||||
@@ -114,11 +119,6 @@ namespace Barotrauma.Items.Components
|
|||||||
public override void AddToGUIUpdateList()
|
public override void AddToGUIUpdateList()
|
||||||
{
|
{
|
||||||
base.AddToGUIUpdateList();
|
base.AddToGUIUpdateList();
|
||||||
if (!string.IsNullOrEmpty(DisplayedWelcomeMessage))
|
|
||||||
{
|
|
||||||
ShowOnDisplay(DisplayedWelcomeMessage);
|
|
||||||
DisplayedWelcomeMessage = "";
|
|
||||||
}
|
|
||||||
if (shouldSelectInputBox)
|
if (shouldSelectInputBox)
|
||||||
{
|
{
|
||||||
inputBox.Select();
|
inputBox.Select();
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ namespace Barotrauma.Items.Components
|
|||||||
drawOffset = sub.DrawPosition + sub.HiddenSubPosition;
|
drawOffset = sub.DrawPosition + sub.HiddenSubPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
float depth = item.IsSelected ? 0.0f : Screen.Selected is SubEditorScreen editor && editor.WiringMode ? 0.00002f : wireSprite.Depth + ((item.ID % 100) * 0.00001f);
|
float depth = item.IsSelected ? 0.0f : SubEditorScreen.IsWiringMode() ? 0.02f : wireSprite.Depth + ((item.ID % 100) * 0.00001f);
|
||||||
|
|
||||||
if (item.IsHighlighted)
|
if (item.IsHighlighted)
|
||||||
{
|
{
|
||||||
@@ -261,7 +261,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUI.DrawRectangle(spriteBatch, drawPos + new Vector2(-3, -3), new Vector2(6, 6), item.Color, true, 0.0f);
|
GUI.DrawRectangle(spriteBatch, drawPos + new Vector2(-3, -3), new Vector2(6, 6), item.Color, true, 0.015f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -288,70 +288,75 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (!editing || GUI.DisableHUD || !item.IsSelected) { return; }
|
if (!editing || GUI.DisableHUD || !item.IsSelected) { return; }
|
||||||
|
|
||||||
float widgetRadius = 60.0f;
|
const float widgetRadius = 60.0f;
|
||||||
|
|
||||||
GUI.DrawLine(spriteBatch,
|
|
||||||
drawPos,
|
|
||||||
drawPos + new Vector2((float)Math.Cos(minRotation), (float)Math.Sin(minRotation)) * widgetRadius,
|
|
||||||
GUI.Style.Green);
|
|
||||||
|
|
||||||
GUI.DrawLine(spriteBatch,
|
|
||||||
drawPos,
|
|
||||||
drawPos + new Vector2((float)Math.Cos(maxRotation), (float)Math.Sin(maxRotation)) * widgetRadius,
|
|
||||||
GUI.Style.Green);
|
|
||||||
|
|
||||||
GUI.DrawLine(spriteBatch,
|
GUI.DrawLine(spriteBatch,
|
||||||
drawPos,
|
drawPos,
|
||||||
drawPos + new Vector2((float)Math.Cos((maxRotation + minRotation) / 2), (float)Math.Sin((maxRotation + minRotation) / 2)) * widgetRadius,
|
drawPos + new Vector2((float)Math.Cos((maxRotation + minRotation) / 2), (float)Math.Sin((maxRotation + minRotation) / 2)) * widgetRadius,
|
||||||
Color.LightGreen);
|
Color.LightGreen);
|
||||||
|
|
||||||
|
const float coneRadius = 300.0f;
|
||||||
|
float radians = maxRotation - minRotation;
|
||||||
|
float circleRadius = coneRadius / Screen.Selected.Cam.Zoom * GUI.Scale;
|
||||||
|
float lineThickness = 1f / Screen.Selected.Cam.Zoom;
|
||||||
|
|
||||||
|
if (radians > Math.PI * 2)
|
||||||
|
{
|
||||||
|
spriteBatch.DrawCircle(drawPos, circleRadius, 180, GUI.Style.Red, thickness: lineThickness);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spriteBatch.DrawSector(drawPos, circleRadius, radians, (int)Math.Abs(90 * radians), GUI.Style.Green, offset: minRotation, thickness: lineThickness);
|
||||||
|
}
|
||||||
|
|
||||||
Widget minRotationWidget = GetWidget("minrotation", spriteBatch, size: 10, initMethod: (widget) =>
|
Widget minRotationWidget = GetWidget("minrotation", spriteBatch, size: 10, initMethod: (widget) =>
|
||||||
{
|
{
|
||||||
widget.Selected += () =>
|
widget.Selected += () =>
|
||||||
{
|
{
|
||||||
oldRotation = RotationLimits;
|
oldRotation = RotationLimits;
|
||||||
};
|
};
|
||||||
widget.MouseDown += () =>
|
widget.MouseDown += () =>
|
||||||
{
|
{
|
||||||
widget.color = GUI.Style.Green;
|
widget.color = GUI.Style.Green;
|
||||||
prevAngle = minRotation;
|
prevAngle = minRotation;
|
||||||
};
|
};
|
||||||
widget.Deselected += () =>
|
widget.Deselected += () =>
|
||||||
{
|
{
|
||||||
widget.color = Color.Yellow;
|
widget.color = Color.Yellow;
|
||||||
item.CreateEditingHUD();
|
item.CreateEditingHUD();
|
||||||
if (SubEditorScreen.IsSubEditor())
|
if (SubEditorScreen.IsSubEditor())
|
||||||
{
|
{
|
||||||
SubEditorScreen.StoreCommand(new PropertyCommand(this, "RotationLimits", RotationLimits, oldRotation));
|
SubEditorScreen.StoreCommand(new PropertyCommand(this, "RotationLimits", RotationLimits, oldRotation));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
widget.MouseHeld += (deltaTime) =>
|
widget.MouseHeld += (deltaTime) =>
|
||||||
{
|
{
|
||||||
minRotation = GetRotationAngle(GetDrawPos());
|
minRotation = GetRotationAngle(GetDrawPos());
|
||||||
if (minRotation > maxRotation)
|
if (minRotation > maxRotation)
|
||||||
{
|
{
|
||||||
float temp = minRotation;
|
float temp = minRotation;
|
||||||
minRotation = maxRotation;
|
minRotation = maxRotation;
|
||||||
maxRotation = temp;
|
maxRotation = temp;
|
||||||
}
|
}
|
||||||
MapEntity.DisableSelect = true;
|
RotationLimits = RotationLimits;
|
||||||
};
|
MapEntity.DisableSelect = true;
|
||||||
widget.PreUpdate += (deltaTime) =>
|
};
|
||||||
{
|
widget.PreUpdate += (deltaTime) =>
|
||||||
widget.DrawPos = new Vector2(widget.DrawPos.X, -widget.DrawPos.Y);
|
{
|
||||||
widget.DrawPos = Screen.Selected.Cam.WorldToScreen(widget.DrawPos);
|
widget.DrawPos = new Vector2(widget.DrawPos.X, -widget.DrawPos.Y);
|
||||||
};
|
widget.DrawPos = Screen.Selected.Cam.WorldToScreen(widget.DrawPos);
|
||||||
widget.PostUpdate += (deltaTime) =>
|
};
|
||||||
{
|
widget.PostUpdate += (deltaTime) =>
|
||||||
widget.DrawPos = Screen.Selected.Cam.ScreenToWorld(widget.DrawPos);
|
{
|
||||||
widget.DrawPos = new Vector2(widget.DrawPos.X, -widget.DrawPos.Y);
|
widget.DrawPos = Screen.Selected.Cam.ScreenToWorld(widget.DrawPos);
|
||||||
};
|
widget.DrawPos = new Vector2(widget.DrawPos.X, -widget.DrawPos.Y);
|
||||||
widget.PreDraw += (sprtBtch, deltaTime) =>
|
};
|
||||||
{
|
widget.PreDraw += (sprtBtch, deltaTime) =>
|
||||||
widget.tooltip = "Min: " + (int)MathHelper.ToDegrees(minRotation);
|
{
|
||||||
widget.DrawPos = GetDrawPos() + new Vector2((float)Math.Cos(minRotation), (float)Math.Sin(minRotation)) * widgetRadius;
|
widget.tooltip = "Min: " + (int)MathHelper.ToDegrees(minRotation);
|
||||||
widget.Update(deltaTime);
|
widget.DrawPos = GetDrawPos() + new Vector2((float)Math.Cos(minRotation), (float)Math.Sin(minRotation)) * coneRadius / Screen.Selected.Cam.Zoom * GUI.Scale;
|
||||||
};
|
widget.Update(deltaTime);
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
Widget maxRotationWidget = GetWidget("maxrotation", spriteBatch, size: 10, initMethod: (widget) =>
|
Widget maxRotationWidget = GetWidget("maxrotation", spriteBatch, size: 10, initMethod: (widget) =>
|
||||||
@@ -383,6 +388,7 @@ namespace Barotrauma.Items.Components
|
|||||||
minRotation = maxRotation;
|
minRotation = maxRotation;
|
||||||
maxRotation = temp;
|
maxRotation = temp;
|
||||||
}
|
}
|
||||||
|
RotationLimits = RotationLimits;
|
||||||
MapEntity.DisableSelect = true;
|
MapEntity.DisableSelect = true;
|
||||||
};
|
};
|
||||||
widget.PreUpdate += (deltaTime) =>
|
widget.PreUpdate += (deltaTime) =>
|
||||||
@@ -398,7 +404,7 @@ namespace Barotrauma.Items.Components
|
|||||||
widget.PreDraw += (sprtBtch, deltaTime) =>
|
widget.PreDraw += (sprtBtch, deltaTime) =>
|
||||||
{
|
{
|
||||||
widget.tooltip = "Max: " + (int)MathHelper.ToDegrees(maxRotation);
|
widget.tooltip = "Max: " + (int)MathHelper.ToDegrees(maxRotation);
|
||||||
widget.DrawPos = GetDrawPos() + new Vector2((float)Math.Cos(maxRotation), (float)Math.Sin(maxRotation)) * widgetRadius;
|
widget.DrawPos = GetDrawPos() + new Vector2((float)Math.Cos(maxRotation), (float)Math.Sin(maxRotation)) * coneRadius / Screen.Selected.Cam.Zoom * GUI.Scale;
|
||||||
widget.Update(deltaTime);
|
widget.Update(deltaTime);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -580,7 +586,6 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
Launch(projectile, launchRotation: newTargetRotation);
|
Launch(projectile, launchRotation: newTargetRotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -439,7 +439,7 @@ namespace Barotrauma
|
|||||||
protected virtual void ControlInput(Camera cam)
|
protected virtual void ControlInput(Camera cam)
|
||||||
{
|
{
|
||||||
// Note that these targets are static. Therefore the outcome is the same if this method is called multiple times or only once.
|
// Note that these targets are static. Therefore the outcome is the same if this method is called multiple times or only once.
|
||||||
if (selectedSlot != null && !DraggingItemToWorld)
|
if (selectedSlot != null && !DraggingItemToWorld && cam.GetZoomAmountFromPrevious() <= 0.25f)
|
||||||
{
|
{
|
||||||
cam.Freeze = true;
|
cam.Freeze = true;
|
||||||
}
|
}
|
||||||
@@ -477,8 +477,12 @@ namespace Barotrauma
|
|||||||
SoundPlayer.PlayUISound(GUISoundType.PickItem);
|
SoundPlayer.PlayUISound(GUISoundType.PickItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
SubEditorScreen.BulkItemBufferInUse = true;
|
if (!item.Removed)
|
||||||
SubEditorScreen.BulkItemBuffer.Add(new AddOrDeleteCommand(new List<MapEntity> { item }, true));
|
{
|
||||||
|
SubEditorScreen.BulkItemBufferInUse = SubEditorScreen.ItemRemoveMutex;
|
||||||
|
SubEditorScreen.BulkItemBuffer.Add(new AddOrDeleteCommand(new List<MapEntity> { item }, true));
|
||||||
|
}
|
||||||
|
|
||||||
item.OwnInventory?.DeleteAllItems();
|
item.OwnInventory?.DeleteAllItems();
|
||||||
item.Remove();
|
item.Remove();
|
||||||
}
|
}
|
||||||
@@ -688,6 +692,18 @@ namespace Barotrauma
|
|||||||
subInventory.Update(deltaTime, cam, true);
|
subInventory.Update(deltaTime, cam, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ClearSubInventories()
|
||||||
|
{
|
||||||
|
if (highlightedSubInventorySlots.Count == 0) return;
|
||||||
|
|
||||||
|
foreach (SlotReference highlightedSubInventorySlot in highlightedSubInventorySlots)
|
||||||
|
{
|
||||||
|
highlightedSubInventorySlot.Inventory.HideTimer = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
highlightedSubInventorySlots.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
public virtual void Draw(SpriteBatch spriteBatch, bool subInventory = false)
|
public virtual void Draw(SpriteBatch spriteBatch, bool subInventory = false)
|
||||||
{
|
{
|
||||||
if (slots == null || isSubInventory != subInventory) return;
|
if (slots == null || isSubInventory != subInventory) return;
|
||||||
|
|||||||
@@ -62,9 +62,9 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool DrawBelowWater => (!(Screen.Selected is SubEditorScreen editor) || !editor.WiringMode || !isWire) && (base.DrawBelowWater || ParentInventory is CharacterInventory);
|
public override bool DrawBelowWater => (!(Screen.Selected is SubEditorScreen editor) || !editor.WiringMode || !isWire || !isLogic) && (base.DrawBelowWater || ParentInventory is CharacterInventory);
|
||||||
|
|
||||||
public override bool DrawOverWater => base.DrawOverWater || (IsSelected || Screen.Selected is SubEditorScreen editor && editor.WiringMode) && isWire;
|
public override bool DrawOverWater => base.DrawOverWater || (IsSelected || Screen.Selected is SubEditorScreen editor && editor.WiringMode) && (isWire || isLogic);
|
||||||
|
|
||||||
private GUITextBlock itemInUseWarning;
|
private GUITextBlock itemInUseWarning;
|
||||||
private GUITextBlock ItemInUseWarning
|
private GUITextBlock ItemInUseWarning
|
||||||
@@ -240,6 +240,10 @@ namespace Barotrauma
|
|||||||
Color color = IsHighlighted && !GUI.DisableItemHighlights && Screen.Selected != GameMain.GameScreen ? GUI.Style.Orange : GetSpriteColor();
|
Color color = IsHighlighted && !GUI.DisableItemHighlights && Screen.Selected != GameMain.GameScreen ? GUI.Style.Orange : GetSpriteColor();
|
||||||
//if (IsSelected && editing) color = Color.Lerp(color, Color.Gold, 0.5f);
|
//if (IsSelected && editing) color = Color.Lerp(color, Color.Gold, 0.5f);
|
||||||
|
|
||||||
|
bool isWiringMode = editing && SubEditorScreen.IsWiringMode() && !isWire && parentInventory == null;
|
||||||
|
bool renderTransparent = isWiringMode && GetComponent<ConnectionPanel>() == null;
|
||||||
|
if (renderTransparent) { color *= 0.15f; }
|
||||||
|
|
||||||
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 : condition;
|
||||||
@@ -269,6 +273,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
float depth = GetDrawDepth();
|
float depth = GetDrawDepth();
|
||||||
|
if (isWiringMode && isLogic && !PlayerInput.IsShiftDown()) { depth = 0.01f; }
|
||||||
if (activeSprite != null)
|
if (activeSprite != null)
|
||||||
{
|
{
|
||||||
SpriteEffects oldEffects = activeSprite.effects;
|
SpriteEffects oldEffects = activeSprite.effects;
|
||||||
@@ -296,6 +301,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
||||||
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, -rotationRad) * Scale;
|
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, -rotationRad) * Scale;
|
||||||
|
if (flippedX && Prefab.CanSpriteFlipX) { offset.X = -offset.X; }
|
||||||
|
if (flippedY && Prefab.CanSpriteFlipY) { offset.Y = -offset.Y; }
|
||||||
decorativeSprite.Sprite.DrawTiled(spriteBatch,
|
decorativeSprite.Sprite.DrawTiled(spriteBatch,
|
||||||
new Vector2(DrawPosition.X + offset.X - rect.Width / 2, -(DrawPosition.Y + offset.Y + rect.Height / 2)),
|
new Vector2(DrawPosition.X + offset.X - rect.Width / 2, -(DrawPosition.Y + offset.Y + rect.Height / 2)),
|
||||||
size, color: color,
|
size, color: color,
|
||||||
@@ -316,11 +323,18 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
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);
|
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 (Infector != null && Infector.ParentBallastFlora.HasBrokenThrough)
|
||||||
|
{
|
||||||
|
Prefab.InfectedSprite?.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y) + drawOffset, color, Prefab.InfectedSprite.Origin, rotationRad, Scale, activeSprite.effects, depth - 0.001f);
|
||||||
|
Prefab.DamagedInfectedSprite?.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y) + drawOffset, Infector.HealthColor, Prefab.DamagedInfectedSprite.Origin, rotationRad, Scale, activeSprite.effects, depth - 0.002f);
|
||||||
|
}
|
||||||
foreach (var decorativeSprite in Prefab.DecorativeSprites)
|
foreach (var decorativeSprite in Prefab.DecorativeSprites)
|
||||||
{
|
{
|
||||||
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
||||||
float rot = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState);
|
float rot = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState);
|
||||||
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, -rotationRad) * Scale;
|
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, -rotationRad) * Scale;
|
||||||
|
if (flippedX && Prefab.CanSpriteFlipX) { offset.X = -offset.X; }
|
||||||
|
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,
|
||||||
rotationRad + rot, decorativeSprite.Scale * Scale, activeSprite.effects,
|
rotationRad + rot, decorativeSprite.Scale * Scale, activeSprite.effects,
|
||||||
depth: Math.Min(depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth), 0.999f));
|
depth: Math.Min(depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth), 0.999f));
|
||||||
@@ -367,7 +381,8 @@ namespace Barotrauma
|
|||||||
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
||||||
float rotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState);
|
float rotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState);
|
||||||
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, -rotationRad) * Scale;
|
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, -rotationRad) * Scale;
|
||||||
|
if (flippedX && Prefab.CanSpriteFlipX) { offset.X = -offset.X; }
|
||||||
|
if (flippedY && Prefab.CanSpriteFlipY) { offset.Y = -offset.Y; }
|
||||||
var ca = (float)Math.Cos(-body.Rotation);
|
var ca = (float)Math.Cos(-body.Rotation);
|
||||||
var sa = (float)Math.Sin(-body.Rotation);
|
var sa = (float)Math.Sin(-body.Rotation);
|
||||||
Vector2 transformedOffset = new Vector2(ca * offset.X + sa * offset.Y, -sa * offset.X + ca * offset.Y);
|
Vector2 transformedOffset = new Vector2(ca * offset.X + sa * offset.Y, -sa * offset.X + ca * offset.Y);
|
||||||
@@ -386,9 +401,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
||||||
float rotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState);
|
float rotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState);
|
||||||
var (xOff, yOff) = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, -rotationRad) * Scale;
|
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, -rotationRad) * Scale;
|
||||||
|
if (flippedX && Prefab.CanSpriteFlipX) { offset.X = -offset.X; }
|
||||||
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + xOff, -(DrawPosition.Y + yOff)), color,
|
if (flippedY && Prefab.CanSpriteFlipY) { offset.Y = -offset.Y; }
|
||||||
|
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + offset.X, -(DrawPosition.Y + offset.Y)), color,
|
||||||
rotation, decorativeSprite.Scale * Scale, activeSprite.effects,
|
rotation, decorativeSprite.Scale * Scale, activeSprite.effects,
|
||||||
depth: depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth));
|
depth: depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth));
|
||||||
}
|
}
|
||||||
@@ -417,6 +433,14 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (editing && IsSelected && PlayerInput.KeyDown(Keys.Space))
|
||||||
|
{
|
||||||
|
if (GetComponent<ElectricalDischarger>() is { } discharger)
|
||||||
|
{
|
||||||
|
discharger.DrawElectricity(spriteBatch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!editing || (body != null && !body.Enabled))
|
if (!editing || (body != null && !body.Enabled))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -506,6 +530,18 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (Screen.Selected != GameMain.SubEditorScreen) { return; }
|
if (Screen.Selected != GameMain.SubEditorScreen) { return; }
|
||||||
|
|
||||||
|
if (GetComponent<ElectricalDischarger>() is { } discharger)
|
||||||
|
{
|
||||||
|
if (PlayerInput.KeyDown(Keys.Space))
|
||||||
|
{
|
||||||
|
discharger.FindNodes(WorldPosition, discharger.Range);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
discharger.IsActive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (Character.Controlled == null) { activeHUDs.Clear(); }
|
if (Character.Controlled == null) { activeHUDs.Clear(); }
|
||||||
|
|
||||||
if (!Linkable) { return; }
|
if (!Linkable) { return; }
|
||||||
@@ -1341,6 +1377,10 @@ namespace Barotrauma
|
|||||||
|
|
||||||
DebugConsole.Log($"Received entity spawn message for item \"{itemName}\" (identifier: {itemIdentifier}, id: {itemId})");
|
DebugConsole.Log($"Received entity spawn message for item \"{itemName}\" (identifier: {itemIdentifier}, id: {itemId})");
|
||||||
|
|
||||||
|
var itemPrefab = string.IsNullOrEmpty(itemIdentifier) ?
|
||||||
|
MapEntityPrefab.Find(itemName, null, showErrorMessages: false) as ItemPrefab :
|
||||||
|
MapEntityPrefab.Find(itemName, itemIdentifier, showErrorMessages: false) as ItemPrefab;
|
||||||
|
|
||||||
Vector2 pos = Vector2.Zero;
|
Vector2 pos = Vector2.Zero;
|
||||||
Submarine sub = null;
|
Submarine sub = null;
|
||||||
int itemContainerIndex = -1;
|
int itemContainerIndex = -1;
|
||||||
@@ -1369,16 +1409,24 @@ namespace Barotrauma
|
|||||||
string tags = "";
|
string tags = "";
|
||||||
if (tagsChanged)
|
if (tagsChanged)
|
||||||
{
|
{
|
||||||
tags = msg.ReadString();
|
string[] addedTags = msg.ReadString().Split(',');
|
||||||
|
string[] removedTags = msg.ReadString().Split(',');
|
||||||
|
if (itemPrefab != null)
|
||||||
|
{
|
||||||
|
tags = string.Join(',',itemPrefab.Tags.Where(t => !removedTags.Contains(t)).Concat(addedTags));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool isNameTag = msg.ReadBoolean();
|
||||||
|
string writtenName = "";
|
||||||
|
if (isNameTag)
|
||||||
|
{
|
||||||
|
writtenName = msg.ReadString();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!spawn) return null;
|
if (!spawn) { return null; }
|
||||||
|
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
|
|
||||||
var itemPrefab = string.IsNullOrEmpty(itemIdentifier) ?
|
|
||||||
MapEntityPrefab.Find(itemName, null, showErrorMessages: false) as ItemPrefab :
|
|
||||||
MapEntityPrefab.Find(itemName, itemIdentifier, showErrorMessages: false) as ItemPrefab;
|
|
||||||
if (itemPrefab == null)
|
if (itemPrefab == null)
|
||||||
{
|
{
|
||||||
string errorMsg = "Failed to spawn item, prefab not found (name: " + (itemName ?? "null") + ", identifier: " + (itemIdentifier ?? "null") + ")";
|
string errorMsg = "Failed to spawn item, prefab not found (name: " + (itemName ?? "null") + ", identifier: " + (itemIdentifier ?? "null") + ")";
|
||||||
@@ -1425,9 +1473,8 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var item = new Item(itemPrefab, pos, sub)
|
var item = new Item(itemPrefab, pos, sub, id: itemId)
|
||||||
{
|
{
|
||||||
ID = itemId,
|
|
||||||
SpawnedInOutpost = spawnedInOutpost
|
SpawnedInOutpost = spawnedInOutpost
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1442,6 +1489,11 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
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>();
|
||||||
|
if (nameTag != null)
|
||||||
|
{
|
||||||
|
nameTag.WrittenName = writtenName;
|
||||||
|
}
|
||||||
|
|
||||||
if (sub != null)
|
if (sub != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ namespace Barotrauma
|
|||||||
public Dictionary<int, List<DecorativeSprite>> DecorativeSpriteGroups = new Dictionary<int, List<DecorativeSprite>>();
|
public Dictionary<int, List<DecorativeSprite>> DecorativeSpriteGroups = new Dictionary<int, List<DecorativeSprite>>();
|
||||||
public Sprite InventoryIcon;
|
public Sprite InventoryIcon;
|
||||||
public Sprite MinimapIcon;
|
public Sprite MinimapIcon;
|
||||||
|
public Sprite InfectedSprite;
|
||||||
|
public Sprite DamagedInfectedSprite;
|
||||||
|
|
||||||
//only used to display correct color in the sub editor, item instances have their own property that can be edited on a per-item basis
|
//only used to display correct color in the sub editor, item instances have their own property that can be edited on a per-item basis
|
||||||
[Serialize("1.0,1.0,1.0,1.0", false)]
|
[Serialize("1.0,1.0,1.0,1.0", false)]
|
||||||
|
|||||||
@@ -0,0 +1,333 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
using Barotrauma.Items.Components;
|
||||||
|
using Barotrauma.Networking;
|
||||||
|
using FarseerPhysics;
|
||||||
|
using FarseerPhysics.Dynamics;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
|
namespace Barotrauma.MapCreatures.Behavior
|
||||||
|
{
|
||||||
|
partial class BallastFloraBehavior
|
||||||
|
{
|
||||||
|
|
||||||
|
// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global, UnusedAutoPropertyAccessor.Global, MemberCanBePrivate.Global
|
||||||
|
internal class DamageParticle
|
||||||
|
{
|
||||||
|
[Serialize(defaultValue: "", isSaveable: false)]
|
||||||
|
public string Identifier { get; set; } = "";
|
||||||
|
|
||||||
|
[Serialize(defaultValue: 0f, isSaveable: false)]
|
||||||
|
public float MinRotation { get; set; }
|
||||||
|
|
||||||
|
[Serialize(defaultValue: 0f, isSaveable: false)]
|
||||||
|
public float MaxRotation { get; set; }
|
||||||
|
|
||||||
|
[Serialize(defaultValue: 0f, isSaveable: false)]
|
||||||
|
public float MinVelocity { get; set; }
|
||||||
|
|
||||||
|
[Serialize(defaultValue: 0f, isSaveable: false)]
|
||||||
|
public float MaxVelocity { get; set; }
|
||||||
|
|
||||||
|
private float RandRotation() => Rand.Range(MinRotation, MaxRotation);
|
||||||
|
private float RandVelocity() => Rand.Range(MinVelocity, MaxVelocity);
|
||||||
|
|
||||||
|
public void Emit(Vector2 pos)
|
||||||
|
{
|
||||||
|
GameMain.ParticleManager.CreateParticle(Identifier, pos, RandRotation(), RandVelocity());
|
||||||
|
}
|
||||||
|
|
||||||
|
public DamageParticle(XElement element)
|
||||||
|
{
|
||||||
|
SerializableProperty.DeserializeProperties(this, element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Sprite? branchAtlas, decayAtlas;
|
||||||
|
public readonly Dictionary<VineTileType, VineSprite> BranchSprites = new Dictionary<VineTileType, VineSprite>();
|
||||||
|
public readonly List<Sprite> FlowerSprites = new List<Sprite>(), DamagedFlowerSprites = new List<Sprite>();
|
||||||
|
public readonly List<Sprite> HiddenFlowerSprites = new List<Sprite>();
|
||||||
|
public readonly List<Sprite> LeafSprites = new List<Sprite>(), DamagedLeafSprites = new List<Sprite>();
|
||||||
|
|
||||||
|
public readonly List<DamageParticle> DamageParticles = new List<DamageParticle>();
|
||||||
|
|
||||||
|
partial void LoadPrefab(XElement element)
|
||||||
|
{
|
||||||
|
string? branchAtlasPath = element.GetAttributeString("branchatlas", null);
|
||||||
|
string? decayAtlasPath = element.GetAttributeString("decayatlas", null);
|
||||||
|
|
||||||
|
if (branchAtlasPath != null)
|
||||||
|
{
|
||||||
|
branchAtlas = new Sprite(branchAtlasPath, Rectangle.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decayAtlasPath != null)
|
||||||
|
{
|
||||||
|
decayAtlas = new Sprite(decayAtlasPath, Rectangle.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (XElement subElement in element.Elements())
|
||||||
|
{
|
||||||
|
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||||
|
{
|
||||||
|
case "branchsprite":
|
||||||
|
var tileType = subElement.GetAttributeString("type", null);
|
||||||
|
VineTileType type = Enum.Parse<VineTileType>(tileType);
|
||||||
|
BranchSprites.Add(type, new VineSprite(subElement));
|
||||||
|
break;
|
||||||
|
case "flowersprite":
|
||||||
|
FlowerSprites.Add(new Sprite(subElement));
|
||||||
|
break;
|
||||||
|
case "damagedflowersprite":
|
||||||
|
DamagedFlowerSprites.Add(new Sprite(subElement));
|
||||||
|
break;
|
||||||
|
case "hiddenflowersprite":
|
||||||
|
HiddenFlowerSprites.Add(new Sprite(subElement));
|
||||||
|
break;
|
||||||
|
case "leafsprite":
|
||||||
|
LeafSprites.Add(new Sprite(subElement));
|
||||||
|
break;
|
||||||
|
case "damagedleafsprite":
|
||||||
|
DamagedLeafSprites.Add(new Sprite(subElement));
|
||||||
|
break;
|
||||||
|
case "damageparticle":
|
||||||
|
DamageParticles.Add(new DamageParticle(subElement));
|
||||||
|
break;
|
||||||
|
case "targets":
|
||||||
|
LoadTargets(subElement);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
flowerVariants = FlowerSprites.Count;
|
||||||
|
leafVariants = LeafSprites.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateShapnel(Vector2 pos)
|
||||||
|
{
|
||||||
|
float particleAmount = Rand.Range(16, 32);
|
||||||
|
for (int i = 0; i < particleAmount; i++)
|
||||||
|
{
|
||||||
|
GameMain.ParticleManager.CreateParticle("shrapnel", pos, Rand.Vector(Rand.Range(-50f, 50.0f)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateDamageParticle(BallastFloraBranch branch, float damage)
|
||||||
|
{
|
||||||
|
Vector2 pos = GetWorldPosition() + branch.Position;
|
||||||
|
int amount = (int)Math.Clamp(damage / 10f, 1, 10);
|
||||||
|
for (int i = 0; i < amount; i++)
|
||||||
|
{
|
||||||
|
foreach (DamageParticle particle in DamageParticles)
|
||||||
|
{
|
||||||
|
particle.Emit(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly Color DarkColor = new Color(25, 25, 25);
|
||||||
|
|
||||||
|
public void Draw(SpriteBatch spriteBatch)
|
||||||
|
{
|
||||||
|
const float zStep = 0.00001f;
|
||||||
|
float leafDepth = zStep;
|
||||||
|
float flowerDepth = zStep;
|
||||||
|
|
||||||
|
if (GameMain.DebugDraw)
|
||||||
|
{
|
||||||
|
foreach (Body body in bodies)
|
||||||
|
{
|
||||||
|
Vector2 pos = Parent.Submarine.DrawPosition + ConvertUnits.ToDisplayUnits(body.Position);
|
||||||
|
pos.Y = -pos.Y;
|
||||||
|
GUI.DrawRectangle(spriteBatch, pos, 32f, 32f, 0f, Color.Cyan, 0.1f, thickness: 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var (key, steps) in IgnoredTargets)
|
||||||
|
{
|
||||||
|
string label = $"Ignored \"{key.Name}\" for {steps} steps";
|
||||||
|
var (sizeX, sizeY) = GUI.SubHeadingFont.MeasureString(label);
|
||||||
|
Vector2 targetPos = key.WorldPosition;
|
||||||
|
targetPos.Y = -targetPos.Y;
|
||||||
|
GUI.DrawString(spriteBatch, targetPos - new Vector2(sizeX / 2f, sizeY), label, GUI.Style.Red, font: GUI.SubHeadingFont);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (BallastFloraBranch branch in Branches)
|
||||||
|
{
|
||||||
|
Vector2 pos = Parent.DrawPosition + Offset + branch.Position;
|
||||||
|
pos.Y = -pos.Y;
|
||||||
|
|
||||||
|
float depth = BranchDepth;
|
||||||
|
|
||||||
|
float layer1 = depth + 0.01f,
|
||||||
|
layer2 = depth + 0.02f,
|
||||||
|
layer3 = depth + 0.03f;
|
||||||
|
|
||||||
|
VineSprite branchSprite = BranchSprites[branch.Type];
|
||||||
|
|
||||||
|
Color branchColor = Color.White;
|
||||||
|
|
||||||
|
if (GameMain.DebugDraw)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
Vector2 basePos = Parent.WorldPosition;
|
||||||
|
foreach (var (from, to) in debugSearchLines)
|
||||||
|
{
|
||||||
|
Vector2 pos1 = basePos - from;
|
||||||
|
pos1.Y = -pos1.Y;
|
||||||
|
Vector2 pos2 = basePos - to;
|
||||||
|
pos2.Y = -pos2.Y;
|
||||||
|
GUI.DrawLine(spriteBatch, pos1, pos2, GUI.Style.Yellow * 0.8f, width: 4);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
string label = "";
|
||||||
|
|
||||||
|
if (branch == Branches[^1])
|
||||||
|
{
|
||||||
|
label += $"Current State: {StateMachine.State?.GetType().Name ?? "null!"}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StateMachine.State is GrowToTargetState targetState)
|
||||||
|
{
|
||||||
|
if (targetState.TargetBranches.Contains(branch))
|
||||||
|
{
|
||||||
|
GUI.DrawRectangle(spriteBatch, pos, branch.Rect.Width, branch.Rect.Height, 0f, Color.Red, thickness: 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetState.TargetBranches[^1] == branch)
|
||||||
|
{
|
||||||
|
label += $"Target: {targetState.Target.Name}\n";
|
||||||
|
|
||||||
|
Vector2 targetPos = targetState.Target.WorldPosition;
|
||||||
|
targetPos.Y = -targetPos.Y;
|
||||||
|
GUI.DrawLine(spriteBatch, pos, targetPos, Color.Red, width: 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (sizeX, sizeY) = GUI.SubHeadingFont.MeasureString(label);
|
||||||
|
GUI.DrawString(spriteBatch, pos - new Vector2(sizeX / 2f, branch.Rect.Height + sizeY), label, Color.White, font: GUI.SubHeadingFont);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isDamaged = branch.Health < branch.MaxHealth;
|
||||||
|
|
||||||
|
if (HasBrokenThrough)
|
||||||
|
{
|
||||||
|
if (branchAtlas != null)
|
||||||
|
{
|
||||||
|
spriteBatch.Draw(branchAtlas.Texture, pos + branch.offset, branchSprite.SourceRect, branchColor, 0f, branchSprite.AbsoluteOrigin, BaseBranchScale * branch.VineStep, SpriteEffects.None, layer2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decayAtlas != null && isDamaged)
|
||||||
|
{
|
||||||
|
spriteBatch.Draw(decayAtlas.Texture, pos + branch.offset, branchSprite.SourceRect, branch.HealthColor, 0f, branchSprite.AbsoluteOrigin, BaseBranchScale * branch.VineStep, SpriteEffects.None, layer2 - zStep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (branch.FlowerConfig.Variant >= 0)
|
||||||
|
{
|
||||||
|
int variant = branch.FlowerConfig.Variant;
|
||||||
|
Sprite flowerSprite = HasBrokenThrough ? FlowerSprites[variant] : HiddenFlowerSprites[variant];
|
||||||
|
float flowerScale = BaseFlowerScale * branch.FlowerConfig.Scale * branch.FlowerStep;
|
||||||
|
|
||||||
|
if (HasBrokenThrough) { flowerScale *= branch.Pulse; }
|
||||||
|
|
||||||
|
flowerSprite.Draw(spriteBatch, pos, branchColor, flowerSprite.Origin, scale: flowerScale, rotate: branch.FlowerConfig.Rotation, depth: layer1 - flowerDepth);
|
||||||
|
if (isDamaged && HasBrokenThrough && DamagedFlowerSprites.Count > variant)
|
||||||
|
{
|
||||||
|
DamagedFlowerSprites[variant].Draw(spriteBatch, pos, branch.HealthColor, flowerSprite.Origin, scale: flowerScale, rotate: branch.FlowerConfig.Rotation, depth: layer1 - flowerDepth - zStep);
|
||||||
|
}
|
||||||
|
flowerDepth -= zStep;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (branch.LeafConfig.Variant >= 0 && HasBrokenThrough)
|
||||||
|
{
|
||||||
|
int variant = branch.LeafConfig.Variant;
|
||||||
|
Sprite leafSprite = LeafSprites[variant];
|
||||||
|
leafSprite.Draw(spriteBatch, pos, branchColor, leafSprite.Origin, scale: BaseLeafScale * branch.LeafConfig.Scale * branch.FlowerStep, rotate: branch.LeafConfig.Rotation, depth: layer3 + leafDepth);
|
||||||
|
if (isDamaged && DamagedLeafSprites.Count > variant)
|
||||||
|
{
|
||||||
|
DamagedLeafSprites[variant].Draw(spriteBatch, pos, branch.HealthColor, leafSprite.Origin, scale: BaseLeafScale * branch.LeafConfig.Scale * branch.FlowerStep, rotate: branch.LeafConfig.Rotation, depth: layer3 + leafDepth - zStep);
|
||||||
|
}
|
||||||
|
leafDepth += zStep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void ClientRead(IReadMessage msg, NetworkHeader header)
|
||||||
|
{
|
||||||
|
switch (header)
|
||||||
|
{
|
||||||
|
case NetworkHeader.Infect:
|
||||||
|
ushort itemId = msg.ReadUInt16();
|
||||||
|
bool infect = msg.ReadBoolean();
|
||||||
|
if (Entity.FindEntityByID(itemId) is Item item)
|
||||||
|
{
|
||||||
|
if (infect)
|
||||||
|
{
|
||||||
|
ClaimTarget(item, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RemoveClaim(itemId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NetworkHeader.BranchCreate:
|
||||||
|
int parentId = msg.ReadInt32();
|
||||||
|
BallastFloraBranch branch = ReadBranch(msg);
|
||||||
|
|
||||||
|
UpdateConnections(branch, Branches.FirstOrDefault(b => b.ID == parentId));
|
||||||
|
Branches.Add(branch);
|
||||||
|
OnBranchGrowthSuccess(branch);
|
||||||
|
break;
|
||||||
|
case NetworkHeader.BranchRemove:
|
||||||
|
|
||||||
|
int removedBranchId = msg.ReadInt32();
|
||||||
|
BallastFloraBranch removedBranch = Branches.FirstOrDefault(b => b.ID == removedBranchId);
|
||||||
|
if (removedBranch != null) { RemoveBranch(removedBranch); }
|
||||||
|
break;
|
||||||
|
case NetworkHeader.BranchDamage:
|
||||||
|
|
||||||
|
int damageBranchId = msg.ReadInt32();
|
||||||
|
float damage = msg.ReadSingle();
|
||||||
|
float health = msg.ReadSingle();
|
||||||
|
BallastFloraBranch damagedBranch = Branches.FirstOrDefault(b => b.ID == damageBranchId);
|
||||||
|
if (damagedBranch != null)
|
||||||
|
{
|
||||||
|
CreateDamageParticle(damagedBranch, damage);
|
||||||
|
damagedBranch.Health = health;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NetworkHeader.Kill:
|
||||||
|
Kill();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
PowerConsumptionTimer = msg.ReadSingle();
|
||||||
|
}
|
||||||
|
|
||||||
|
private BallastFloraBranch ReadBranch(IReadMessage msg)
|
||||||
|
{
|
||||||
|
int id = msg.ReadInt32();
|
||||||
|
byte type = (byte) msg.ReadRangedInteger(0b0000, 0b1111);
|
||||||
|
byte sides = (byte) msg.ReadRangedInteger(0b0000, 0b1111);
|
||||||
|
int flowerConfig = msg.ReadRangedInteger(0, 0xFFF);
|
||||||
|
int leafConfig = msg.ReadRangedInteger(0, 0xFFF);
|
||||||
|
int maxHealth = msg.ReadUInt16();
|
||||||
|
int posX = msg.ReadInt32(), posY = msg.ReadInt32();
|
||||||
|
Vector2 pos = new Vector2(posX * VineTile.Size, posY * VineTile.Size);
|
||||||
|
|
||||||
|
return new BallastFloraBranch(this, pos, (VineTileType)type, FoliageConfig.Deserialize(flowerConfig), FoliageConfig.Deserialize(leafConfig))
|
||||||
|
{
|
||||||
|
ID = id,
|
||||||
|
Sides = (TileSide) sides
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -36,8 +36,8 @@ namespace Barotrauma
|
|||||||
Rand.Range(worldPosition.Y - size.Y, worldPosition.Y + 20.0f));
|
Rand.Range(worldPosition.Y - size.Y, worldPosition.Y + 20.0f));
|
||||||
|
|
||||||
Vector2 particleVel = new Vector2(
|
Vector2 particleVel = new Vector2(
|
||||||
(particlePos.X - (worldPosition.X + size.X / 2.0f)),
|
particlePos.X - (worldPosition.X + size.X / 2.0f),
|
||||||
(float)Math.Sqrt(size.X) * Rand.Range(0.0f, 15.0f) * growModifier);
|
Math.Max((float)Math.Sqrt(size.X) * Rand.Range(0.0f, 15.0f) * growModifier, 0.0f));
|
||||||
|
|
||||||
particleVel.X = MathHelper.Clamp(particleVel.X, -200.0f, 200.0f);
|
particleVel.X = MathHelper.Clamp(particleVel.X, -200.0f, 200.0f);
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,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.MapCreatures.Behavior;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -48,7 +49,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return decals.Count > 0;
|
return decals.Count > 0 || BallastFlora != null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,6 +66,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public override bool IsVisible(Rectangle worldView)
|
public override bool IsVisible(Rectangle worldView)
|
||||||
{
|
{
|
||||||
|
if (BallastFlora != null) { return true; }
|
||||||
|
|
||||||
if (Screen.Selected != GameMain.SubEditorScreen && !GameMain.DebugDraw)
|
if (Screen.Selected != GameMain.SubEditorScreen && !GameMain.DebugDraw)
|
||||||
{
|
{
|
||||||
if (decals.Count == 0 && paintAmount < minimumPaintAmountToDraw) { return false; }
|
if (decals.Count == 0 && paintAmount < minimumPaintAmountToDraw) { return false; }
|
||||||
@@ -229,6 +232,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (back && Screen.Selected != GameMain.SubEditorScreen)
|
if (back && Screen.Selected != GameMain.SubEditorScreen)
|
||||||
{
|
{
|
||||||
|
BallastFlora?.Draw(spriteBatch);
|
||||||
DrawDecals(spriteBatch);
|
DrawDecals(spriteBatch);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -244,7 +248,7 @@ namespace Barotrauma
|
|||||||
alpha = Math.Min((float)(Timing.TotalTime - lastAmbientLightEditTime) / hideTimeAfterEdit - 1.0f, 1.0f);
|
alpha = Math.Min((float)(Timing.TotalTime - lastAmbientLightEditTime) / hideTimeAfterEdit - 1.0f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle drawRect =
|
Rectangle drawRect =
|
||||||
Submarine == null ? rect : new Rectangle((int)(Submarine.DrawPosition.X + rect.X), (int)(Submarine.DrawPosition.Y + rect.Y), rect.Width, rect.Height);
|
Submarine == null ? rect : new Rectangle((int)(Submarine.DrawPosition.X + rect.X), (int)(Submarine.DrawPosition.Y + rect.Y), rect.Width, rect.Height);
|
||||||
|
|
||||||
if ((IsSelected || IsHighlighted) && editing)
|
if ((IsSelected || IsHighlighted) && editing)
|
||||||
@@ -607,6 +611,26 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage message, float sendingTime)
|
public void ClientRead(ServerNetObject type, IReadMessage message, float sendingTime)
|
||||||
{
|
{
|
||||||
|
bool isBallastFloraUpdate = message.ReadBoolean();
|
||||||
|
if (isBallastFloraUpdate)
|
||||||
|
{
|
||||||
|
BallastFloraBehavior.NetworkHeader header = (BallastFloraBehavior.NetworkHeader) message.ReadByte();
|
||||||
|
if (header == BallastFloraBehavior.NetworkHeader.Spawn)
|
||||||
|
{
|
||||||
|
string identifier = message.ReadString();
|
||||||
|
float x = message.ReadSingle();
|
||||||
|
float y = message.ReadSingle();
|
||||||
|
BallastFlora = new BallastFloraBehavior(this, BallastFloraPrefab.Find(identifier), new Vector2(x, y), firstGrowth: true)
|
||||||
|
{
|
||||||
|
PowerConsumptionTimer = message.ReadSingle()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (BallastFlora != null)
|
||||||
|
{
|
||||||
|
BallastFlora.ClientRead(message, header);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
remoteWaterVolume = message.ReadRangedSingle(0.0f, 1.5f, 8) * Volume;
|
remoteWaterVolume = message.ReadRangedSingle(0.0f, 1.5f, 8) * Volume;
|
||||||
remoteOxygenPercentage = message.ReadRangedSingle(0.0f, 100.0f, 8);
|
remoteOxygenPercentage = message.ReadRangedSingle(0.0f, 100.0f, 8);
|
||||||
|
|
||||||
|
|||||||
+194
-34
@@ -1,20 +1,26 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using Barotrauma.SpriteDeformations;
|
||||||
|
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.Xml.Linq;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
|
|
||||||
class BackgroundCreature : ISteerable
|
class BackgroundCreature : ISteerable
|
||||||
{
|
{
|
||||||
const float MaxDepth = 100.0f;
|
const float MaxDepth = 10000.0f;
|
||||||
|
|
||||||
const float CheckWallsInterval = 5.0f;
|
const float CheckWallsInterval = 5.0f;
|
||||||
|
|
||||||
public bool Enabled;
|
public bool Visible;
|
||||||
|
|
||||||
private BackgroundCreaturePrefab prefab;
|
public readonly BackgroundCreaturePrefab Prefab;
|
||||||
|
|
||||||
|
private readonly List<SpriteDeformation> uniqueSpriteDeformations = new List<SpriteDeformation>();
|
||||||
|
private readonly List<SpriteDeformation> spriteDeformations = new List<SpriteDeformation>();
|
||||||
|
private readonly List<SpriteDeformation> lightSpriteDeformations = new List<SpriteDeformation>();
|
||||||
|
|
||||||
private Vector2 position;
|
private Vector2 position;
|
||||||
|
|
||||||
@@ -22,9 +28,11 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private float depth;
|
private float depth;
|
||||||
|
|
||||||
private SteeringManager steeringManager;
|
private float alpha = 1.0f;
|
||||||
|
|
||||||
private float checkWallsTimer;
|
private readonly SteeringManager steeringManager;
|
||||||
|
|
||||||
|
private float checkWallsTimer, flashTimer;
|
||||||
|
|
||||||
private float wanderZPhase;
|
private float wanderZPhase;
|
||||||
private Vector2 obstacleDiff;
|
private Vector2 obstacleDiff;
|
||||||
@@ -33,9 +41,16 @@ namespace Barotrauma
|
|||||||
public Swarm Swarm;
|
public Swarm Swarm;
|
||||||
|
|
||||||
Vector2 drawPosition;
|
Vector2 drawPosition;
|
||||||
public Vector2 TransformedPosition
|
|
||||||
|
public Vector2[,] CurrentSpriteDeformation
|
||||||
{
|
{
|
||||||
get { return drawPosition; }
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
public Vector2[,] CurrentLightSpriteDeformation
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector2 SimPosition
|
public Vector2 SimPosition
|
||||||
@@ -61,8 +76,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public BackgroundCreature(BackgroundCreaturePrefab prefab, Vector2 position)
|
public BackgroundCreature(BackgroundCreaturePrefab prefab, Vector2 position)
|
||||||
{
|
{
|
||||||
this.prefab = prefab;
|
this.Prefab = prefab;
|
||||||
|
|
||||||
this.position = position;
|
this.position = position;
|
||||||
|
|
||||||
drawPosition = position;
|
drawPosition = position;
|
||||||
@@ -70,18 +84,73 @@ namespace Barotrauma
|
|||||||
steeringManager = new SteeringManager(this);
|
steeringManager = new SteeringManager(this);
|
||||||
|
|
||||||
velocity = new Vector3(
|
velocity = new Vector3(
|
||||||
Rand.Range(-prefab.Speed, prefab.Speed),
|
Rand.Range(-prefab.Speed, prefab.Speed, Rand.RandSync.ClientOnly),
|
||||||
Rand.Range(-prefab.Speed, prefab.Speed),
|
Rand.Range(-prefab.Speed, prefab.Speed, Rand.RandSync.ClientOnly),
|
||||||
Rand.Range(0.0f, prefab.WanderZAmount));
|
Rand.Range(0.0f, prefab.WanderZAmount, Rand.RandSync.ClientOnly));
|
||||||
|
|
||||||
checkWallsTimer = Rand.Range(0.0f, CheckWallsInterval);
|
checkWallsTimer = Rand.Range(0.0f, CheckWallsInterval, Rand.RandSync.ClientOnly);
|
||||||
|
|
||||||
|
foreach (XElement subElement in prefab.Config.Elements())
|
||||||
|
{
|
||||||
|
List<SpriteDeformation> deformationList = null;
|
||||||
|
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||||
|
{
|
||||||
|
case "deformablesprite":
|
||||||
|
deformationList = spriteDeformations;
|
||||||
|
break;
|
||||||
|
case "deformablelightsprite":
|
||||||
|
deformationList = lightSpriteDeformations;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
foreach (XElement animationElement in subElement.Elements())
|
||||||
|
{
|
||||||
|
SpriteDeformation deformation = null;
|
||||||
|
int sync = animationElement.GetAttributeInt("sync", -1);
|
||||||
|
if (sync > -1)
|
||||||
|
{
|
||||||
|
string typeName = animationElement.GetAttributeString("type", "").ToLowerInvariant();
|
||||||
|
deformation = uniqueSpriteDeformations.Find(d => d.TypeName == typeName && d.Sync == sync);
|
||||||
|
}
|
||||||
|
if (deformation == null)
|
||||||
|
{
|
||||||
|
deformation = SpriteDeformation.Load(animationElement, prefab.Name);
|
||||||
|
if (deformation != null)
|
||||||
|
{
|
||||||
|
uniqueSpriteDeformations.Add(deformation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (deformation != null)
|
||||||
|
{
|
||||||
|
deformationList.Add(deformation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update(float deltaTime)
|
public void Update(float deltaTime)
|
||||||
{
|
{
|
||||||
position += new Vector2(velocity.X, velocity.Y) * deltaTime;
|
position += new Vector2(velocity.X, velocity.Y) * deltaTime;
|
||||||
depth = MathHelper.Clamp(depth + velocity.Z * deltaTime, 0.0f, MaxDepth);
|
depth = MathHelper.Clamp(depth + velocity.Z * deltaTime, Prefab.MinDepth, Prefab.MaxDepth * 10);
|
||||||
|
|
||||||
|
if (Prefab.FlashInterval > 0.0f)
|
||||||
|
{
|
||||||
|
flashTimer -= deltaTime;
|
||||||
|
if (flashTimer > 0.0f)
|
||||||
|
{
|
||||||
|
alpha = 0.0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//value goes from 0 to 1 and back to 0 during the flash
|
||||||
|
alpha = (float)Math.Sin(-flashTimer / Prefab.FlashDuration * MathHelper.Pi) * PerlinNoise.GetPerlin((float)Timing.TotalTime * 0.1f, (float)Timing.TotalTime * 0.2f);
|
||||||
|
if (flashTimer < -Prefab.FlashDuration)
|
||||||
|
{
|
||||||
|
flashTimer = Prefab.FlashInterval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
checkWallsTimer -= deltaTime;
|
checkWallsTimer -= deltaTime;
|
||||||
if (checkWallsTimer <= 0.0f && Level.Loaded != null)
|
if (checkWallsTimer <= 0.0f && Level.Loaded != null)
|
||||||
@@ -134,54 +203,145 @@ namespace Barotrauma
|
|||||||
float midPointDist = Vector2.Distance(SimPosition, midPoint) * 100.0f;
|
float midPointDist = Vector2.Distance(SimPosition, midPoint) * 100.0f;
|
||||||
if (midPointDist > Swarm.MaxDistance)
|
if (midPointDist > Swarm.MaxDistance)
|
||||||
{
|
{
|
||||||
steeringManager.SteeringSeek(midPoint, ((midPointDist / Swarm.MaxDistance) - 1.0f) * prefab.Speed);
|
steeringManager.SteeringSeek(midPoint, ((midPointDist / Swarm.MaxDistance) - 1.0f) * Prefab.Speed);
|
||||||
}
|
}
|
||||||
steeringManager.SteeringManual(deltaTime, Swarm.AvgVelocity() * Swarm.Cohesion);
|
steeringManager.SteeringManual(deltaTime, Swarm.AvgVelocity() * Swarm.Cohesion);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prefab.WanderAmount > 0.0f)
|
if (Prefab.WanderAmount > 0.0f)
|
||||||
{
|
{
|
||||||
steeringManager.SteeringWander(prefab.Speed);
|
steeringManager.SteeringWander(Prefab.Speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obstacleDiff != Vector2.Zero)
|
if (obstacleDiff != Vector2.Zero)
|
||||||
{
|
{
|
||||||
steeringManager.SteeringManual(deltaTime, -obstacleDiff * (1.0f - obstacleDist / 5000.0f) * prefab.Speed);
|
steeringManager.SteeringManual(deltaTime, -obstacleDiff * (1.0f - obstacleDist / 5000.0f) * Prefab.Speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
steeringManager.Update(prefab.Speed);
|
steeringManager.Update(Prefab.Speed);
|
||||||
|
|
||||||
if (prefab.WanderZAmount > 0.0f)
|
if (Prefab.WanderZAmount > 0.0f)
|
||||||
{
|
{
|
||||||
wanderZPhase += Rand.Range(-prefab.WanderZAmount, prefab.WanderZAmount);
|
wanderZPhase += Rand.Range(-Prefab.WanderZAmount, Prefab.WanderZAmount);
|
||||||
velocity.Z = (float)Math.Sin(wanderZPhase) * prefab.Speed;
|
velocity.Z = (float)Math.Sin(wanderZPhase) * Prefab.Speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
velocity = Vector3.Lerp(velocity, new Vector3(Steering.X, Steering.Y, velocity.Z), deltaTime);
|
velocity = Vector3.Lerp(velocity, new Vector3(Steering.X, Steering.Y, velocity.Z), deltaTime);
|
||||||
|
|
||||||
|
UpdateDeformations(deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawLightSprite(SpriteBatch spriteBatch, Camera cam)
|
||||||
|
{
|
||||||
|
Draw(spriteBatch, cam, Prefab.LightSprite, Prefab.DeformableLightSprite, CurrentLightSpriteDeformation, Color.White * alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Draw(SpriteBatch spriteBatch, Camera cam)
|
public void Draw(SpriteBatch spriteBatch, Camera cam)
|
||||||
{
|
{
|
||||||
|
Draw(spriteBatch,
|
||||||
|
cam,
|
||||||
|
Prefab.Sprite,
|
||||||
|
Prefab.DeformableSprite,
|
||||||
|
CurrentSpriteDeformation,
|
||||||
|
Color.Lerp(Color.White, Level.Loaded.BackgroundColor, depth / Math.Max(MaxDepth, Prefab.MaxDepth)) * alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Draw(SpriteBatch spriteBatch, Camera cam, Sprite sprite, DeformableSprite deformableSprite, Vector2[,] currentSpriteDeformation, Color color)
|
||||||
|
{
|
||||||
|
if (sprite == null && deformableSprite == null) { return; }
|
||||||
|
if (color.A == 0) { return; }
|
||||||
|
|
||||||
float rotation = 0.0f;
|
float rotation = 0.0f;
|
||||||
if (!prefab.DisableRotation)
|
if (!Prefab.DisableRotation)
|
||||||
{
|
{
|
||||||
rotation = MathUtils.VectorToAngle(new Vector2(velocity.X, -velocity.Y));
|
rotation = MathUtils.VectorToAngle(new Vector2(velocity.X, -velocity.Y));
|
||||||
if (velocity.X < 0.0f) rotation -= MathHelper.Pi;
|
if (velocity.X < 0.0f) { rotation -= MathHelper.Pi; }
|
||||||
}
|
}
|
||||||
|
|
||||||
drawPosition = position;
|
drawPosition = GetDrawPosition(cam);
|
||||||
if (depth > 0.0f)
|
|
||||||
|
float scale = GetScale();
|
||||||
|
sprite?.Draw(spriteBatch,
|
||||||
|
new Vector2(drawPosition.X, -drawPosition.Y),
|
||||||
|
color,
|
||||||
|
rotation,
|
||||||
|
scale,
|
||||||
|
Prefab.DisableFlipping || velocity.X > 0.0f ? SpriteEffects.None : SpriteEffects.FlipHorizontally,
|
||||||
|
Math.Min(depth / MaxDepth, 1.0f));
|
||||||
|
|
||||||
|
if (deformableSprite != null)
|
||||||
|
{
|
||||||
|
if (currentSpriteDeformation != null)
|
||||||
|
{
|
||||||
|
deformableSprite.Deform(currentSpriteDeformation);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
deformableSprite.Reset();
|
||||||
|
}
|
||||||
|
deformableSprite?.Draw(cam,
|
||||||
|
new Vector3(drawPosition.X, drawPosition.Y, Math.Min(depth / 10000.0f, 1.0f)),
|
||||||
|
deformableSprite.Origin,
|
||||||
|
rotation,
|
||||||
|
Vector2.One * scale,
|
||||||
|
color,
|
||||||
|
mirror: Prefab.DisableFlipping || velocity.X <= 0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 GetDrawPosition(Camera cam)
|
||||||
|
{
|
||||||
|
Vector2 drawPosition = WorldPosition;
|
||||||
|
if (depth >= 0)
|
||||||
{
|
{
|
||||||
Vector2 camOffset = drawPosition - cam.WorldViewCenter;
|
Vector2 camOffset = drawPosition - cam.WorldViewCenter;
|
||||||
drawPosition -= camOffset * (depth / MaxDepth) * 0.05f;
|
drawPosition -= camOffset * depth / MaxDepth;
|
||||||
}
|
}
|
||||||
|
return drawPosition;
|
||||||
|
}
|
||||||
|
|
||||||
prefab.Sprite.Draw(spriteBatch,
|
public float GetScale()
|
||||||
new Vector2(drawPosition.X, -drawPosition.Y),
|
{
|
||||||
Color.Lerp(Color.White, Level.Loaded.BackgroundColor, (depth / MaxDepth) * 0.2f),
|
return Math.Max(1.0f - depth / MaxDepth, 0.05f) * Prefab.Scale;
|
||||||
rotation, (1.0f - (depth / MaxDepth) * 0.2f) * prefab.Scale,
|
}
|
||||||
velocity.X > 0.0f ? SpriteEffects.None : SpriteEffects.FlipHorizontally,
|
|
||||||
(depth / MaxDepth));
|
public Rectangle GetExtents(Camera cam)
|
||||||
|
{
|
||||||
|
Vector2 min = GetDrawPosition(cam);
|
||||||
|
Vector2 max = min;
|
||||||
|
|
||||||
|
float scale = GetScale();
|
||||||
|
GetSpriteExtents(Prefab.Sprite, ref min, ref max);
|
||||||
|
GetSpriteExtents(Prefab.LightSprite, ref min, ref max);
|
||||||
|
GetSpriteExtents(Prefab.DeformableSprite?.Sprite, ref min, ref max);
|
||||||
|
GetSpriteExtents(Prefab.DeformableLightSprite?.Sprite, ref min, ref max);
|
||||||
|
|
||||||
|
return new Rectangle(min.ToPoint(), (max - min).ToPoint());
|
||||||
|
|
||||||
|
void GetSpriteExtents(Sprite sprite, ref Vector2 min, ref Vector2 max)
|
||||||
|
{
|
||||||
|
if (sprite == null) { return; }
|
||||||
|
min.X = Math.Min(min.X, min.X - sprite.size.X * sprite.RelativeOrigin.X * scale);
|
||||||
|
min.Y = Math.Min(min.Y, min.Y - sprite.size.Y * sprite.RelativeOrigin.Y * scale);
|
||||||
|
max.X = Math.Max(max.X, max.X + sprite.size.X * (1.0f - sprite.RelativeOrigin.X) * scale);
|
||||||
|
max.Y = Math.Max(max.Y, max.Y + sprite.size.Y * (1.0f - sprite.RelativeOrigin.Y) * scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateDeformations(float deltaTime)
|
||||||
|
{
|
||||||
|
foreach (SpriteDeformation deformation in uniqueSpriteDeformations)
|
||||||
|
{
|
||||||
|
deformation.Update(deltaTime);
|
||||||
|
}
|
||||||
|
if (spriteDeformations.Count > 0)
|
||||||
|
{
|
||||||
|
CurrentSpriteDeformation = SpriteDeformation.GetDeformation(spriteDeformations, Prefab.DeformableSprite.Size);
|
||||||
|
}
|
||||||
|
if (lightSpriteDeformations.Count > 0)
|
||||||
|
{
|
||||||
|
CurrentLightSpriteDeformation = SpriteDeformation.GetDeformation(lightSpriteDeformations, Prefab.DeformableLightSprite.Size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+53
-34
@@ -9,14 +9,14 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
class BackgroundCreatureManager
|
class BackgroundCreatureManager
|
||||||
{
|
{
|
||||||
const int MaxSprites = 100;
|
const int MaxCreatures = 100;
|
||||||
|
|
||||||
const float CheckActiveInterval = 1.0f;
|
const float VisibilityCheckInterval = 1.0f;
|
||||||
|
|
||||||
private float checkActiveTimer;
|
private float checkVisibleTimer;
|
||||||
|
|
||||||
private List<BackgroundCreaturePrefab> prefabs = new List<BackgroundCreaturePrefab>();
|
private readonly List<BackgroundCreaturePrefab> prefabs = new List<BackgroundCreaturePrefab>();
|
||||||
private List<BackgroundCreature> activeSprites = new List<BackgroundCreature>();
|
private readonly List<BackgroundCreature> creatures = new List<BackgroundCreature>();
|
||||||
|
|
||||||
public BackgroundCreatureManager(string configPath)
|
public BackgroundCreatureManager(string configPath)
|
||||||
{
|
{
|
||||||
@@ -60,25 +60,25 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SpawnSprites(int count, Vector2? position = null)
|
public void SpawnCreatures(Level level, int count, Vector2? position = null)
|
||||||
{
|
{
|
||||||
activeSprites.Clear();
|
creatures.Clear();
|
||||||
|
|
||||||
if (prefabs.Count == 0) return;
|
if (prefabs.Count == 0) { return; }
|
||||||
|
|
||||||
count = Math.Min(count, MaxSprites);
|
count = Math.Min(count, MaxCreatures);
|
||||||
|
|
||||||
for (int i = 0; i < count; i++ )
|
List<BackgroundCreaturePrefab> availablePrefabs = new List<BackgroundCreaturePrefab>(prefabs);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
Vector2 pos = Vector2.Zero;
|
Vector2 pos = Vector2.Zero;
|
||||||
|
|
||||||
if (position == null)
|
if (position == null)
|
||||||
{
|
{
|
||||||
var wayPoints = WayPoint.WayPointList.FindAll(wp => wp.Submarine==null);
|
var wayPoints = WayPoint.WayPointList.FindAll(wp => wp.Submarine == null);
|
||||||
if (wayPoints.Any())
|
if (wayPoints.Any())
|
||||||
{
|
{
|
||||||
WayPoint wp = wayPoints[Rand.Int(wayPoints.Count, Rand.RandSync.ClientOnly)];
|
WayPoint wp = wayPoints[Rand.Int(wayPoints.Count, Rand.RandSync.ClientOnly)];
|
||||||
|
|
||||||
pos = new Vector2(wp.Rect.X, wp.Rect.Y);
|
pos = new Vector2(wp.Rect.X, wp.Rect.Y);
|
||||||
pos += Rand.Vector(200.0f, Rand.RandSync.ClientOnly);
|
pos += Rand.Vector(200.0f, Rand.RandSync.ClientOnly);
|
||||||
}
|
}
|
||||||
@@ -92,60 +92,79 @@ namespace Barotrauma
|
|||||||
pos = (Vector2)position;
|
pos = (Vector2)position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var prefab = ToolBox.SelectWeightedRandom(availablePrefabs, availablePrefabs.Select(p => p.GetCommonness(level.GenerationParams)).ToList(), Rand.RandSync.ClientOnly);
|
||||||
var prefab = prefabs[Rand.Int(prefabs.Count, Rand.RandSync.ClientOnly)];
|
if (prefab == null) { break; }
|
||||||
|
|
||||||
int amount = Rand.Range(prefab.SwarmMin, prefab.SwarmMax, Rand.RandSync.ClientOnly);
|
int amount = Rand.Range(prefab.SwarmMin, prefab.SwarmMax, Rand.RandSync.ClientOnly);
|
||||||
List<BackgroundCreature> swarmMembers = new List<BackgroundCreature>();
|
List<BackgroundCreature> swarmMembers = new List<BackgroundCreature>();
|
||||||
|
|
||||||
for (int n = 0; n < amount; n++)
|
for (int n = 0; n < amount; n++)
|
||||||
{
|
{
|
||||||
var newSprite = new BackgroundCreature(prefab, pos);
|
var creature = new BackgroundCreature(prefab, pos + Rand.Vector(Rand.Range(0.0f, prefab.SwarmRadius, Rand.RandSync.ClientOnly), Rand.RandSync.ClientOnly));
|
||||||
activeSprites.Add(newSprite);
|
creatures.Add(creature);
|
||||||
swarmMembers.Add(newSprite);
|
swarmMembers.Add(creature);
|
||||||
}
|
}
|
||||||
if (amount > 0)
|
if (amount > 1)
|
||||||
{
|
{
|
||||||
new Swarm(swarmMembers, prefab.SwarmRadius, prefab.SwarmCohesion);
|
new Swarm(swarmMembers, prefab.SwarmRadius, prefab.SwarmCohesion);
|
||||||
}
|
}
|
||||||
|
if (creatures.Count(c => c.Prefab == prefab) > prefab.MaxCount)
|
||||||
|
{
|
||||||
|
availablePrefabs.Remove(prefab);
|
||||||
|
if (availablePrefabs.Count <= 0) { break; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearSprites()
|
public void Clear()
|
||||||
{
|
{
|
||||||
activeSprites.Clear();
|
creatures.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update(float deltaTime, Camera cam)
|
public void Update(float deltaTime, Camera cam)
|
||||||
{
|
{
|
||||||
if (checkActiveTimer < 0.0f)
|
if (checkVisibleTimer < 0.0f)
|
||||||
{
|
{
|
||||||
foreach (BackgroundCreature sprite in activeSprites)
|
int margin = 500;
|
||||||
|
foreach (BackgroundCreature creature in creatures)
|
||||||
{
|
{
|
||||||
sprite.Enabled = Math.Abs(sprite.TransformedPosition.X - cam.WorldViewCenter.X) < cam.WorldView.Width &&
|
Rectangle extents = creature.GetExtents(cam);
|
||||||
Math.Abs(sprite.TransformedPosition.Y - cam.WorldViewCenter.Y) < cam.WorldView.Height;
|
bool wasVisible = creature.Visible;
|
||||||
|
creature.Visible =
|
||||||
|
extents.Right >= cam.WorldView.X - margin &&
|
||||||
|
extents.X <= cam.WorldView.Right + margin &&
|
||||||
|
extents.Bottom >= cam.WorldView.Y - cam.WorldView.Height - margin &&
|
||||||
|
extents.Y <= cam.WorldView.Y + margin;
|
||||||
}
|
}
|
||||||
|
|
||||||
checkActiveTimer = CheckActiveInterval;
|
checkVisibleTimer = VisibilityCheckInterval;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
checkActiveTimer -= deltaTime;
|
checkVisibleTimer -= deltaTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (BackgroundCreature sprite in activeSprites)
|
foreach (BackgroundCreature creature in creatures)
|
||||||
{
|
{
|
||||||
if (!sprite.Enabled) continue;
|
if (!creature.Visible) { continue; }
|
||||||
sprite.Update(deltaTime);
|
creature.Update(deltaTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Draw(SpriteBatch spriteBatch, Camera cam)
|
public void Draw(SpriteBatch spriteBatch, Camera cam)
|
||||||
{
|
{
|
||||||
foreach (BackgroundCreature sprite in activeSprites)
|
foreach (BackgroundCreature creature in creatures)
|
||||||
{
|
{
|
||||||
if (!sprite.Enabled) continue;
|
if (!creature.Visible) { continue; }
|
||||||
sprite.Draw(spriteBatch, cam);
|
creature.Draw(spriteBatch, cam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawLights(SpriteBatch spriteBatch, Camera cam)
|
||||||
|
{
|
||||||
|
foreach (BackgroundCreature creature in creatures)
|
||||||
|
{
|
||||||
|
if (!creature.Visible) { continue; }
|
||||||
|
creature.DrawLightSprite(spriteBatch, cam);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+93
-26
@@ -1,50 +1,117 @@
|
|||||||
using System.Xml.Linq;
|
using System.Collections.Generic;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
class BackgroundCreaturePrefab
|
class BackgroundCreaturePrefab
|
||||||
{
|
{
|
||||||
public readonly Sprite Sprite;
|
public readonly Sprite Sprite, LightSprite;
|
||||||
|
public readonly DeformableSprite DeformableSprite, DeformableLightSprite;
|
||||||
|
|
||||||
public readonly float Speed;
|
public readonly string Name;
|
||||||
|
|
||||||
public readonly float WanderAmount;
|
public readonly XElement Config;
|
||||||
|
|
||||||
public readonly float WanderZAmount;
|
[Serialize(1.0f, true)]
|
||||||
|
public float Speed { get; private set; }
|
||||||
|
|
||||||
public readonly int SwarmMin, SwarmMax;
|
[Serialize(0.0f, true)]
|
||||||
public readonly float SwarmRadius, SwarmCohesion;
|
public float WanderAmount { get; private set; }
|
||||||
|
|
||||||
public readonly bool DisableRotation;
|
[Serialize(0.0f, true)]
|
||||||
|
public float WanderZAmount { get; private set; }
|
||||||
|
|
||||||
public readonly float Scale;
|
[Serialize(1, true)]
|
||||||
|
public int SwarmMin { get; private set; }
|
||||||
|
|
||||||
|
[Serialize(1, true)]
|
||||||
|
public int SwarmMax { get; private set; }
|
||||||
|
|
||||||
|
[Serialize(200.0f, true)]
|
||||||
|
public float SwarmRadius { get; private set; }
|
||||||
|
|
||||||
|
[Serialize(0.2f, true)]
|
||||||
|
public float SwarmCohesion { get; private set; }
|
||||||
|
|
||||||
|
[Serialize(10.0f, true)]
|
||||||
|
public float MinDepth { get; private set; }
|
||||||
|
|
||||||
|
[Serialize(1000.0f, true)]
|
||||||
|
public float MaxDepth { get; private set; }
|
||||||
|
|
||||||
|
[Serialize(false, true)]
|
||||||
|
public bool DisableRotation { get; private set; }
|
||||||
|
|
||||||
|
[Serialize(false, true)]
|
||||||
|
public bool DisableFlipping { get; private set; }
|
||||||
|
|
||||||
|
[Serialize(1.0f, true)]
|
||||||
|
public float Scale { get; private set; }
|
||||||
|
|
||||||
|
[Serialize(1.0f, true)]
|
||||||
|
public float Commonness { get; private set; }
|
||||||
|
|
||||||
|
[Serialize(1000, true)]
|
||||||
|
public int MaxCount { get; private set; }
|
||||||
|
|
||||||
|
[Serialize(0.0f, true)]
|
||||||
|
public float FlashInterval { get; private set; }
|
||||||
|
|
||||||
|
[Serialize(0.0f, true)]
|
||||||
|
public float FlashDuration { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Overrides the commonness of the object in a specific level type.
|
||||||
|
/// Key = name of the level type, value = commonness in that level type.
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<string, float> OverrideCommonness = new Dictionary<string, float>();
|
||||||
|
|
||||||
public BackgroundCreaturePrefab(XElement element)
|
public BackgroundCreaturePrefab(XElement element)
|
||||||
{
|
{
|
||||||
Speed = element.GetAttributeFloat("speed", 1.0f);
|
Name = element.Name.ToString();
|
||||||
|
|
||||||
WanderAmount = element.GetAttributeFloat("wanderamount", 0.0f);
|
Config = element;
|
||||||
|
|
||||||
WanderZAmount = element.GetAttributeFloat("wanderzamount", 0.0f);
|
SerializableProperty.DeserializeProperties(this, element);
|
||||||
|
|
||||||
SwarmMin = element.GetAttributeInt("swarmmin", 1);
|
|
||||||
SwarmMax = element.GetAttributeInt("swarmmax", 1);
|
|
||||||
|
|
||||||
SwarmRadius = element.GetAttributeFloat("swarmradius", 200.0f);
|
|
||||||
SwarmCohesion = element.GetAttributeFloat("swarmcohesion", 0.2f);
|
|
||||||
|
|
||||||
DisableRotation = element.GetAttributeBool("disablerotation", false);
|
|
||||||
|
|
||||||
Scale = element.GetAttributeFloat("scale", 1.0f);
|
|
||||||
|
|
||||||
foreach (XElement subElement in element.Elements())
|
foreach (XElement subElement in element.Elements())
|
||||||
{
|
{
|
||||||
if (!subElement.Name.ToString().Equals("sprite", System.StringComparison.OrdinalIgnoreCase)) { continue; }
|
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||||
|
{
|
||||||
Sprite = new Sprite(subElement, lazyLoad: true);
|
case "sprite":
|
||||||
break;
|
Sprite = new Sprite(subElement, lazyLoad: true);
|
||||||
|
break;
|
||||||
|
case "deformablesprite":
|
||||||
|
DeformableSprite = new DeformableSprite(subElement, lazyLoad: true);
|
||||||
|
break;
|
||||||
|
case "lightsprite":
|
||||||
|
LightSprite = new Sprite(subElement, lazyLoad: true);
|
||||||
|
break;
|
||||||
|
case "deformablelightsprite":
|
||||||
|
DeformableLightSprite = new DeformableSprite(subElement, lazyLoad: true);
|
||||||
|
break;
|
||||||
|
case "overridecommonness":
|
||||||
|
string levelType = subElement.GetAttributeString("leveltype", "").ToLowerInvariant();
|
||||||
|
if (!OverrideCommonness.ContainsKey(levelType))
|
||||||
|
{
|
||||||
|
OverrideCommonness.Add(levelType, subElement.GetAttributeFloat("commonness", 1.0f));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float GetCommonness(LevelGenerationParams generationParams)
|
||||||
|
{
|
||||||
|
if (generationParams?.Identifier != null &&
|
||||||
|
(OverrideCommonness.TryGetValue(generationParams.Identifier, out float commonness) ||
|
||||||
|
(generationParams.OldIdentifier != null && OverrideCommonness.TryGetValue(generationParams.OldIdentifier, out commonness))))
|
||||||
|
{
|
||||||
|
return commonness;
|
||||||
|
}
|
||||||
|
return Commonness;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using Barotrauma.Extensions;
|
||||||
|
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;
|
||||||
@@ -8,72 +9,73 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
static partial class CaveGenerator
|
static partial class CaveGenerator
|
||||||
{
|
{
|
||||||
public static List<VertexPositionTexture> GenerateRenderVerticeList(List<Vector2[]> triangles)
|
public static List<VertexPositionTexture> GenerateWallVertices(List<Vector2[]> triangles, LevelGenerationParams generationParams, float zCoord)
|
||||||
{
|
{
|
||||||
var verticeList = new List<VertexPositionTexture>();
|
var vertices = new List<VertexPositionTexture>();
|
||||||
for (int i = 0; i < triangles.Count; i++)
|
for (int i = 0; i < triangles.Count; i++)
|
||||||
{
|
{
|
||||||
foreach (Vector2 vertex in triangles[i])
|
foreach (Vector2 vertex in triangles[i])
|
||||||
{
|
{
|
||||||
//shift the coordinates around a bit to make the texture repetition less obvious
|
Vector2 uvCoords = vertex / generationParams.WallTextureSize;
|
||||||
Vector2 uvCoords = new Vector2(
|
vertices.Add(new VertexPositionTexture(new Vector3(vertex, zCoord), uvCoords));
|
||||||
vertex.X / 2000.0f + (float)Math.Sin(vertex.X / 500.0f) * 0.15f,
|
|
||||||
vertex.Y / 2000.0f + (float)Math.Sin(vertex.Y / 700.0f) * 0.15f);
|
|
||||||
|
|
||||||
verticeList.Add(new VertexPositionTexture(new Vector3(vertex, 1.0f), uvCoords));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return verticeList;
|
return vertices;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static VertexPositionTexture[] GenerateWallShapes(List<VoronoiCell> cells, Level level)
|
public static List<VertexPositionTexture> GenerateWallEdgeVertices(List<VoronoiCell> cells, Level level, float zCoord)
|
||||||
{
|
{
|
||||||
float outWardThickness = 30.0f;
|
float outWardThickness = level.GenerationParams.WallEdgeExpandOutwardsAmount;
|
||||||
|
|
||||||
List<VertexPositionTexture> verticeList = new List<VertexPositionTexture>();
|
List<VertexPositionTexture> vertices = new List<VertexPositionTexture>();
|
||||||
foreach (VoronoiCell cell in cells)
|
foreach (VoronoiCell cell in cells)
|
||||||
{
|
{
|
||||||
CompareCCW compare = new CompareCCW(cell.Center);
|
float circumference = 0.0f;
|
||||||
foreach (GraphEdge edge in cell.Edges)
|
foreach (GraphEdge edge in cell.Edges)
|
||||||
{
|
{
|
||||||
if (edge.Cell1 != null && edge.Cell1.Body == null && edge.Cell1.CellType != CellType.Empty) edge.Cell1 = null;
|
circumference += Vector2.Distance(edge.Point1, edge.Point2);
|
||||||
if (edge.Cell2 != null && edge.Cell2.Body == null && edge.Cell2.CellType != CellType.Empty) edge.Cell2 = null;
|
|
||||||
|
|
||||||
if (compare.Compare(edge.Point1, edge.Point2) == -1)
|
|
||||||
{
|
|
||||||
var temp = edge.Point1;
|
|
||||||
edge.Point1 = edge.Point2;
|
|
||||||
edge.Point2 = temp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
foreach (VoronoiCell cell in cells)
|
|
||||||
{
|
|
||||||
foreach (GraphEdge edge in cell.Edges)
|
foreach (GraphEdge edge in cell.Edges)
|
||||||
{
|
{
|
||||||
if (!edge.IsSolid) continue;
|
if (!edge.IsSolid) { continue; }
|
||||||
|
|
||||||
GraphEdge leftEdge = cell.Edges.Find(e => e != edge && (edge.Point1 == e.Point1 || edge.Point1 == e.Point2));
|
GraphEdge leftEdge = cell.Edges.Find(e => e != edge && (edge.Point1.NearlyEquals(e.Point1) || edge.Point1.NearlyEquals(e.Point2)));
|
||||||
GraphEdge rightEdge = cell.Edges.Find(e => e != edge && (edge.Point2 == e.Point1 || edge.Point2 == e.Point2));
|
var leftAdjacentCell = leftEdge?.AdjacentCell(cell);
|
||||||
|
if (leftAdjacentCell != null)
|
||||||
|
{
|
||||||
|
var adjEdge = leftAdjacentCell.Edges.Find(e => e != leftEdge && e.IsSolid && (edge.Point1.NearlyEquals(e.Point1) || edge.Point1.NearlyEquals(e.Point2)));
|
||||||
|
if (adjEdge != null) { leftEdge = adjEdge; }
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphEdge rightEdge = cell.Edges.Find(e => e != edge && (edge.Point2.NearlyEquals(e.Point1) || edge.Point2.NearlyEquals(e.Point2)));
|
||||||
|
var rightAdjacentCell = rightEdge?.AdjacentCell(cell);
|
||||||
|
if (rightAdjacentCell != null)
|
||||||
|
{
|
||||||
|
var adjEdge = rightAdjacentCell.Edges.Find(e => e != rightEdge && e.IsSolid && (edge.Point2.NearlyEquals(e.Point1) || edge.Point2.NearlyEquals(e.Point2)));
|
||||||
|
if (adjEdge != null) { rightEdge = adjEdge; }
|
||||||
|
}
|
||||||
|
|
||||||
Vector2 leftNormal = Vector2.Zero, rightNormal = Vector2.Zero;
|
Vector2 leftNormal = Vector2.Zero, rightNormal = Vector2.Zero;
|
||||||
|
|
||||||
float inwardThickness1 = 100;
|
float inwardThickness1 = level.GenerationParams.WallEdgeExpandInwardsAmount;
|
||||||
float inwardThickness2 = 100;
|
float inwardThickness2 = level.GenerationParams.WallEdgeExpandInwardsAmount;
|
||||||
if (leftEdge != null && !leftEdge.IsSolid)
|
if (leftEdge != null && !leftEdge.IsSolid)
|
||||||
{
|
{
|
||||||
leftNormal = edge.Point1 == leftEdge.Point1 ?
|
leftNormal = edge.Point1.NearlyEquals(leftEdge.Point1) ?
|
||||||
Vector2.Normalize(leftEdge.Point2 - leftEdge.Point1) :
|
Vector2.Normalize(leftEdge.Point2 - leftEdge.Point1) :
|
||||||
Vector2.Normalize(leftEdge.Point1 - leftEdge.Point2);
|
Vector2.Normalize(leftEdge.Point1 - leftEdge.Point2);
|
||||||
inwardThickness1 = Vector2.Distance(leftEdge.Point1, leftEdge.Point2) / 2;
|
}
|
||||||
|
else if (leftEdge != null)
|
||||||
|
{
|
||||||
|
leftNormal = -Vector2.Normalize(edge.GetNormal(cell) + leftEdge.GetNormal(leftAdjacentCell ?? cell));
|
||||||
|
if (!MathUtils.IsValid(leftNormal)) { leftNormal = -edge.GetNormal(cell); }
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
leftNormal = Vector2.Normalize(cell.Center - edge.Point1);
|
leftNormal = Vector2.Normalize(cell.Center - edge.Point1);
|
||||||
inwardThickness1 = Vector2.Distance(edge.Point1, cell.Center) / 2;
|
|
||||||
}
|
}
|
||||||
|
inwardThickness1 = Math.Min(Vector2.Distance(edge.Point1, cell.Center), inwardThickness1);
|
||||||
|
|
||||||
if (!MathUtils.IsValid(leftNormal))
|
if (!MathUtils.IsValid(leftNormal))
|
||||||
{
|
{
|
||||||
@@ -86,7 +88,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (cell.Body != null)
|
if (cell.Body != null)
|
||||||
{
|
{
|
||||||
GameMain.World.Remove(cell.Body);
|
if (GameMain.World.BodyList.Contains(cell.Body)) { GameMain.World.Remove(cell.Body); }
|
||||||
cell.Body = null;
|
cell.Body = null;
|
||||||
}
|
}
|
||||||
leftNormal = Vector2.UnitX;
|
leftNormal = Vector2.UnitX;
|
||||||
@@ -95,16 +97,20 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (rightEdge != null && !rightEdge.IsSolid)
|
if (rightEdge != null && !rightEdge.IsSolid)
|
||||||
{
|
{
|
||||||
rightNormal = edge.Point2 == rightEdge.Point1 ?
|
rightNormal = edge.Point2.NearlyEquals(rightEdge.Point1) ?
|
||||||
Vector2.Normalize(rightEdge.Point2 - rightEdge.Point1) :
|
Vector2.Normalize(rightEdge.Point2 - rightEdge.Point1) :
|
||||||
Vector2.Normalize(rightEdge.Point1 - rightEdge.Point2);
|
Vector2.Normalize(rightEdge.Point1 - rightEdge.Point2);
|
||||||
inwardThickness2 = Vector2.Distance(rightEdge.Point1, rightEdge.Point2) / 2;
|
}
|
||||||
|
else if (rightEdge != null)
|
||||||
|
{
|
||||||
|
rightNormal = -Vector2.Normalize(edge.GetNormal(cell) + rightEdge.GetNormal(rightAdjacentCell ?? cell));
|
||||||
|
if (!MathUtils.IsValid(rightNormal)) { rightNormal = -edge.GetNormal(cell); }
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rightNormal = Vector2.Normalize(cell.Center - edge.Point2);
|
rightNormal = Vector2.Normalize(cell.Center - edge.Point2);
|
||||||
inwardThickness2 = Vector2.Distance(edge.Point2, cell.Center) / 2;
|
|
||||||
}
|
}
|
||||||
|
inwardThickness2 = Math.Min(Vector2.Distance(edge.Point2, cell.Center), inwardThickness2);
|
||||||
|
|
||||||
if (!MathUtils.IsValid(rightNormal))
|
if (!MathUtils.IsValid(rightNormal))
|
||||||
{
|
{
|
||||||
@@ -117,7 +123,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (cell.Body != null)
|
if (cell.Body != null)
|
||||||
{
|
{
|
||||||
GameMain.World.Remove(cell.Body);
|
if (GameMain.World.BodyList.Contains(cell.Body)) { GameMain.World.Remove(cell.Body); }
|
||||||
cell.Body = null;
|
cell.Body = null;
|
||||||
}
|
}
|
||||||
rightNormal = Vector2.UnitX;
|
rightNormal = Vector2.UnitX;
|
||||||
@@ -129,12 +135,11 @@ namespace Barotrauma
|
|||||||
//handle wrapping around 0/360
|
//handle wrapping around 0/360
|
||||||
if (point1UV - point2UV > MathHelper.Pi)
|
if (point1UV - point2UV > MathHelper.Pi)
|
||||||
{
|
{
|
||||||
point2UV += MathHelper.TwoPi;
|
point1UV -= MathHelper.TwoPi;
|
||||||
}
|
}
|
||||||
//the texture wraps around the cell 4 times
|
int textureRepeatCount = (int)Math.Max(circumference / 2 / level.GenerationParams.WallEdgeTextureWidth, 1);
|
||||||
//TODO: define the uv scale in level generation parameters?
|
point1UV = point1UV / MathHelper.TwoPi * textureRepeatCount;
|
||||||
point1UV = point1UV / MathHelper.TwoPi * 4;
|
point2UV = point2UV / MathHelper.TwoPi * textureRepeatCount;
|
||||||
point2UV = point2UV / MathHelper.TwoPi * 4;
|
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
@@ -147,9 +152,9 @@ namespace Barotrauma
|
|||||||
verts[1] = edge.Point2 - rightNormal * outWardThickness;
|
verts[1] = edge.Point2 - rightNormal * outWardThickness;
|
||||||
verts[2] = edge.Point1 + leftNormal * inwardThickness1;
|
verts[2] = edge.Point1 + leftNormal * inwardThickness1;
|
||||||
|
|
||||||
vertPos[0] = new VertexPositionTexture(new Vector3(verts[0], 0.0f), new Vector2(point1UV, 0.0f));
|
vertPos[0] = new VertexPositionTexture(new Vector3(verts[0], zCoord), new Vector2(point1UV, 0.0f));
|
||||||
vertPos[1] = new VertexPositionTexture(new Vector3(verts[1], 0.0f), new Vector2(point2UV, 0.0f));
|
vertPos[1] = new VertexPositionTexture(new Vector3(verts[1], zCoord), new Vector2(point2UV, 0.0f));
|
||||||
vertPos[2] = new VertexPositionTexture(new Vector3(verts[2], 0.0f), new Vector2(point1UV, 0.5f));
|
vertPos[2] = new VertexPositionTexture(new Vector3(verts[2], zCoord), new Vector2(point1UV, 1.0f));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -158,16 +163,16 @@ namespace Barotrauma
|
|||||||
verts[1] = edge.Point2 - rightNormal * outWardThickness;
|
verts[1] = edge.Point2 - rightNormal * outWardThickness;
|
||||||
verts[2] = edge.Point2 + rightNormal * inwardThickness2;
|
verts[2] = edge.Point2 + rightNormal * inwardThickness2;
|
||||||
|
|
||||||
vertPos[0] = new VertexPositionTexture(new Vector3(verts[0], 0.0f), new Vector2(point1UV, 0.5f));
|
vertPos[0] = new VertexPositionTexture(new Vector3(verts[0], zCoord), new Vector2(point1UV, 1.0f));
|
||||||
vertPos[1] = new VertexPositionTexture(new Vector3(verts[1], 0.0f), new Vector2(point2UV, 0.0f));
|
vertPos[1] = new VertexPositionTexture(new Vector3(verts[1], zCoord), new Vector2(point2UV, 0.0f));
|
||||||
vertPos[2] = new VertexPositionTexture(new Vector3(verts[2], 0.0f), new Vector2(point2UV, 0.5f));
|
vertPos[2] = new VertexPositionTexture(new Vector3(verts[2], zCoord), new Vector2(point2UV, 1.0f));
|
||||||
}
|
}
|
||||||
verticeList.AddRange(vertPos);
|
vertices.AddRange(vertPos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return verticeList.ToArray();
|
return vertices;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
partial class DestructibleLevelWall : LevelWall, IDamageable
|
||||||
|
{
|
||||||
|
|
||||||
|
public override float Alpha
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (FadeOutDuration <= 0.0f || FadeOutTimer < FadeOutDuration - 1.0f) { return 1.0f; }
|
||||||
|
return MathHelper.Clamp(FadeOutDuration - FadeOutTimer, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
partial void AddDamageProjSpecific(float damage, Vector2 worldPosition)
|
||||||
|
{
|
||||||
|
if (damage <= 0.0f) { return; }
|
||||||
|
Vector2 particlePos = worldPosition;
|
||||||
|
if (!Cells.Any(c => c.IsPointInside(particlePos)))
|
||||||
|
{
|
||||||
|
bool intersectionFound = false;
|
||||||
|
foreach (var cell in Cells)
|
||||||
|
{
|
||||||
|
foreach (var edge in cell.Edges)
|
||||||
|
{
|
||||||
|
if (MathUtils.GetLineIntersection(worldPosition, cell.Center, edge.Point1 + cell.Translation, edge.Point2 + cell.Translation, out Vector2 intersection))
|
||||||
|
{
|
||||||
|
intersectionFound = true;
|
||||||
|
particlePos = intersection;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (intersectionFound) { break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 particleDir = particlePos - WorldPosition;
|
||||||
|
if (particleDir.LengthSquared() > 0.0001f) { particleDir = Vector2.Normalize(particleDir); }
|
||||||
|
int particleAmount = MathHelper.Clamp((int)damage, 1, 10);
|
||||||
|
for (int i = 0; i < particleAmount; i++)
|
||||||
|
{
|
||||||
|
var particle = GameMain.ParticleManager.CreateParticle("iceshards",
|
||||||
|
particlePos + Rand.Vector(5.0f),
|
||||||
|
particleDir * Rand.Range(200.0f, 500.0f) + Rand.Vector(100.0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetDamage(float damage)
|
||||||
|
{
|
||||||
|
Damage = damage;
|
||||||
|
if (Damage >= MaxHealth && !Destroyed)
|
||||||
|
{
|
||||||
|
CreateFragments();
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,6 +14,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private BackgroundCreatureManager backgroundCreatureManager;
|
private BackgroundCreatureManager backgroundCreatureManager;
|
||||||
|
|
||||||
|
public BackgroundCreatureManager BackgroundCreatureManager => backgroundCreatureManager;
|
||||||
|
|
||||||
public LevelRenderer Renderer => renderer;
|
public LevelRenderer Renderer => renderer;
|
||||||
|
|
||||||
public void ReloadTextures()
|
public void ReloadTextures()
|
||||||
@@ -33,14 +35,6 @@ namespace Barotrauma
|
|||||||
uniqueSprites.Add(sprite);
|
uniqueSprites.Add(sprite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (Sprite specularSprite in levelObj.Prefab.SpecularSprites)
|
|
||||||
{
|
|
||||||
if (!uniqueTextures.Contains(specularSprite.Texture))
|
|
||||||
{
|
|
||||||
uniqueTextures.Add(specularSprite.Texture);
|
|
||||||
uniqueSprites.Add(specularSprite);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Sprite sprite in uniqueSprites)
|
foreach (Sprite sprite in uniqueSprites)
|
||||||
@@ -51,7 +45,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void DrawFront(SpriteBatch spriteBatch, Camera cam)
|
public void DrawFront(SpriteBatch spriteBatch, Camera cam)
|
||||||
{
|
{
|
||||||
if (renderer == null) return;
|
if (renderer == null) { return; }
|
||||||
renderer.Draw(spriteBatch, cam);
|
renderer.Draw(spriteBatch, cam);
|
||||||
|
|
||||||
if (GameMain.DebugDraw && Screen.Selected.Cam.Zoom > 0.1f)
|
if (GameMain.DebugDraw && Screen.Selected.Cam.Zoom > 0.1f)
|
||||||
@@ -126,19 +120,31 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
foreach (LevelWall levelWall in ExtraWalls)
|
bool isGlobalUpdate = msg.ReadBoolean();
|
||||||
|
if (isGlobalUpdate)
|
||||||
{
|
{
|
||||||
if (levelWall.Body.BodyType == BodyType.Static) continue;
|
foreach (LevelWall levelWall in ExtraWalls)
|
||||||
|
|
||||||
Vector2 bodyPos = new Vector2(
|
|
||||||
msg.ReadSingle(),
|
|
||||||
msg.ReadSingle());
|
|
||||||
|
|
||||||
levelWall.MoveState = msg.ReadRangedSingle(0.0f, MathHelper.TwoPi, 16);
|
|
||||||
|
|
||||||
if (Vector2.DistanceSquared(bodyPos, levelWall.Body.Position) > 0.5f)
|
|
||||||
{
|
{
|
||||||
levelWall.Body.SetTransformIgnoreContacts(ref bodyPos, levelWall.Body.Rotation);
|
if (levelWall.Body.BodyType == BodyType.Static) { continue; }
|
||||||
|
|
||||||
|
Vector2 bodyPos = new Vector2(
|
||||||
|
msg.ReadSingle(),
|
||||||
|
msg.ReadSingle());
|
||||||
|
levelWall.MoveState = msg.ReadRangedSingle(0.0f, MathHelper.TwoPi, 16);
|
||||||
|
DestructibleLevelWall destructibleWall = levelWall as DestructibleLevelWall;
|
||||||
|
if (Vector2.DistanceSquared(bodyPos, levelWall.Body.Position) > 0.5f && (destructibleWall == null || !destructibleWall.Destroyed))
|
||||||
|
{
|
||||||
|
levelWall.Body.SetTransformIgnoreContacts(ref bodyPos, levelWall.Body.Rotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int index = msg.ReadUInt16();
|
||||||
|
byte damageByte = msg.ReadByte();
|
||||||
|
if (index < ExtraWalls.Count && ExtraWalls[index] is DestructibleLevelWall destructibleWall)
|
||||||
|
{
|
||||||
|
destructibleWall.SetDamage(destructibleWall.MaxHealth * damageByte / 255.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
using Barotrauma.Lights;
|
using Barotrauma.Lights;
|
||||||
|
using Barotrauma.Networking;
|
||||||
using Barotrauma.Particles;
|
using Barotrauma.Particles;
|
||||||
using Barotrauma.Sounds;
|
using Barotrauma.Sounds;
|
||||||
using Barotrauma.Networking;
|
using Barotrauma.SpriteDeformations;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using Barotrauma.SpriteDeformations;
|
|
||||||
using System.Linq;
|
|
||||||
using FarseerPhysics.Dynamics;
|
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -77,7 +75,6 @@ namespace Barotrauma
|
|||||||
partial void InitProjSpecific()
|
partial void InitProjSpecific()
|
||||||
{
|
{
|
||||||
Sprite?.EnsureLazyLoaded();
|
Sprite?.EnsureLazyLoaded();
|
||||||
SpecularSprite?.EnsureLazyLoaded();
|
|
||||||
Prefab.DeformableSprite?.EnsureLazyLoaded();
|
Prefab.DeformableSprite?.EnsureLazyLoaded();
|
||||||
|
|
||||||
CurrentSwingAmount = Prefab.SwingAmountRad;
|
CurrentSwingAmount = Prefab.SwingAmountRad;
|
||||||
@@ -98,7 +95,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Prefab.LightSourceParams != null)
|
if (Prefab.LightSourceParams != null && Prefab.LightSourceParams.Count > 0)
|
||||||
{
|
{
|
||||||
LightSources = new LightSource[Prefab.LightSourceParams.Count];
|
LightSources = new LightSource[Prefab.LightSourceParams.Count];
|
||||||
LightSourceTriggers = new LevelTrigger[Prefab.LightSourceParams.Count];
|
LightSourceTriggers = new LevelTrigger[Prefab.LightSourceParams.Count];
|
||||||
@@ -232,17 +229,21 @@ namespace Barotrauma
|
|||||||
deformation.Update(deltaTime);
|
deformation.Update(deltaTime);
|
||||||
}
|
}
|
||||||
CurrentSpriteDeformation = SpriteDeformation.GetDeformation(spriteDeformations, ActivePrefab.DeformableSprite.Size);
|
CurrentSpriteDeformation = SpriteDeformation.GetDeformation(spriteDeformations, ActivePrefab.DeformableSprite.Size);
|
||||||
foreach (LightSource lightSource in LightSources)
|
if (LightSources != null)
|
||||||
{
|
{
|
||||||
if (lightSource?.DeformableLightSprite != null)
|
foreach (LightSource lightSource in LightSources)
|
||||||
{
|
{
|
||||||
lightSource.DeformableLightSprite.Deform(CurrentSpriteDeformation);
|
if (lightSource?.DeformableLightSprite != null)
|
||||||
|
{
|
||||||
|
lightSource.DeformableLightSprite.Deform(CurrentSpriteDeformation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdatePositionalDeformation(PositionalDeformation positionalDeformation, float deltaTime)
|
private void UpdatePositionalDeformation(PositionalDeformation positionalDeformation, float deltaTime)
|
||||||
{
|
{
|
||||||
|
if (Triggers == null) { return; }
|
||||||
Matrix matrix = ActivePrefab.DeformableSprite.GetTransform(
|
Matrix matrix = ActivePrefab.DeformableSprite.GetTransform(
|
||||||
Position,
|
Position,
|
||||||
ActivePrefab.DeformableSprite.Origin,
|
ActivePrefab.DeformableSprite.Origin,
|
||||||
@@ -258,7 +259,7 @@ namespace Barotrauma
|
|||||||
Vector2 moveAmount = triggerer.WorldPosition - trigger.TriggererPosition[triggerer];
|
Vector2 moveAmount = triggerer.WorldPosition - trigger.TriggererPosition[triggerer];
|
||||||
|
|
||||||
moveAmount = Vector2.Transform(moveAmount, rotationMatrix);
|
moveAmount = Vector2.Transform(moveAmount, rotationMatrix);
|
||||||
moveAmount /= (ActivePrefab.DeformableSprite.Size * Scale);
|
moveAmount /= ActivePrefab.DeformableSprite.Size * Scale;
|
||||||
moveAmount.Y = -moveAmount.Y;
|
moveAmount.Y = -moveAmount.Y;
|
||||||
|
|
||||||
positionalDeformation.Deform(trigger.WorldPosition, moveAmount, deltaTime, Matrix.Invert(matrix) *
|
positionalDeformation.Deform(trigger.WorldPosition, moveAmount, deltaTime, Matrix.Invert(matrix) *
|
||||||
@@ -269,9 +270,10 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void ClientRead(IReadMessage msg)
|
public void ClientRead(IReadMessage msg)
|
||||||
{
|
{
|
||||||
|
if (Triggers == null) { return; }
|
||||||
for (int i = 0; i < Triggers.Count; i++)
|
for (int i = 0; i < Triggers.Count; i++)
|
||||||
{
|
{
|
||||||
if (!Triggers[i].UseNetworkSyncing) continue;
|
if (!Triggers[i].UseNetworkSyncing) { continue; }
|
||||||
Triggers[i].ClientRead(msg);
|
Triggers[i].ClientRead(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+32
-8
@@ -12,6 +12,8 @@ namespace Barotrauma
|
|||||||
private readonly List<LevelObject> visibleObjectsBack = new List<LevelObject>();
|
private readonly List<LevelObject> visibleObjectsBack = new List<LevelObject>();
|
||||||
private readonly List<LevelObject> visibleObjectsFront = new List<LevelObject>();
|
private readonly List<LevelObject> visibleObjectsFront = new List<LevelObject>();
|
||||||
|
|
||||||
|
private double NextRefreshTime;
|
||||||
|
|
||||||
//Maximum number of visible objects drawn at once. Should be large enough to not have an effect during normal gameplay,
|
//Maximum number of visible objects drawn at once. Should be large enough to not have an effect during normal gameplay,
|
||||||
//but small enough to prevent wrecking performance when zooming out very far
|
//but small enough to prevent wrecking performance when zooming out very far
|
||||||
const int MaxVisibleObjects = 500;
|
const int MaxVisibleObjects = 500;
|
||||||
@@ -38,11 +40,13 @@ namespace Barotrauma
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks which level objects are in camera view and adds them to the visibleObjects lists
|
/// Checks which level objects are in camera view and adds them to the visibleObjects lists
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void RefreshVisibleObjects(Rectangle currentIndices)
|
private void RefreshVisibleObjects(Rectangle currentIndices, float zoom)
|
||||||
{
|
{
|
||||||
visibleObjectsBack.Clear();
|
visibleObjectsBack.Clear();
|
||||||
visibleObjectsFront.Clear();
|
visibleObjectsFront.Clear();
|
||||||
|
|
||||||
|
float minSizeToDraw = MathHelper.Lerp(10.0f, 5.0f, Math.Min(zoom * 20.0f, 1.0f));
|
||||||
|
|
||||||
for (int x = currentIndices.X; x <= currentIndices.Width; x++)
|
for (int x = currentIndices.X; x <= currentIndices.Width; x++)
|
||||||
{
|
{
|
||||||
for (int y = currentIndices.Y; y <= currentIndices.Height; y++)
|
for (int y = currentIndices.Y; y <= currentIndices.Height; y++)
|
||||||
@@ -50,6 +54,22 @@ namespace Barotrauma
|
|||||||
if (objectGrid[x, y] == null) { continue; }
|
if (objectGrid[x, y] == null) { continue; }
|
||||||
foreach (LevelObject obj in objectGrid[x, y])
|
foreach (LevelObject obj in objectGrid[x, y])
|
||||||
{
|
{
|
||||||
|
if (zoom < 0.05f)
|
||||||
|
{
|
||||||
|
//hide if the sprite is very small when zoomed this far out
|
||||||
|
if ((obj.Sprite != null && Math.Min(obj.Sprite.size.X * zoom, obj.Sprite.size.Y * zoom) < 5.0f) ||
|
||||||
|
(obj.ActivePrefab?.DeformableSprite != null && Math.Min(obj.ActivePrefab.DeformableSprite.Sprite.size.X * zoom, obj.ActivePrefab.DeformableSprite.Sprite.size.Y * zoom) < minSizeToDraw))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
float zCutoff = MathHelper.Lerp(5000.0f, 500.0f, (0.05f - zoom) * 20.0f);
|
||||||
|
if (obj.Position.Z > zCutoff)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var objectList = obj.Position.Z >= 0 ? visibleObjectsBack : visibleObjectsFront;
|
var objectList = obj.Position.Z >= 0 ? visibleObjectsBack : visibleObjectsFront;
|
||||||
int drawOrderIndex = 0;
|
int drawOrderIndex = 0;
|
||||||
for (int i = 0; i < objectList.Count; i++)
|
for (int i = 0; i < objectList.Count; i++)
|
||||||
@@ -83,7 +103,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void DrawObjects(SpriteBatch spriteBatch, Camera cam, bool drawFront, bool specular = false)
|
public void DrawObjects(SpriteBatch spriteBatch, Camera cam, bool drawFront)
|
||||||
{
|
{
|
||||||
Rectangle indices = Rectangle.Empty;
|
Rectangle indices = Rectangle.Empty;
|
||||||
indices.X = (int)Math.Floor(cam.WorldView.X / (float)GridSize);
|
indices.X = (int)Math.Floor(cam.WorldView.X / (float)GridSize);
|
||||||
@@ -102,9 +122,14 @@ namespace Barotrauma
|
|||||||
indices.Height = Math.Min(indices.Height, objectGrid.GetLength(1) - 1);
|
indices.Height = Math.Min(indices.Height, objectGrid.GetLength(1) - 1);
|
||||||
|
|
||||||
float z = 0.0f;
|
float z = 0.0f;
|
||||||
if (currentGridIndices != indices)
|
if (currentGridIndices != indices && Timing.TotalTime > NextRefreshTime)
|
||||||
{
|
{
|
||||||
RefreshVisibleObjects(indices);
|
RefreshVisibleObjects(indices, cam.Zoom);
|
||||||
|
if (cam.Zoom < 0.1f)
|
||||||
|
{
|
||||||
|
//when zoomed very far out, refresh a little less often
|
||||||
|
NextRefreshTime = Timing.TotalTime + MathHelper.Lerp(1.0f, 0.0f, cam.Zoom * 10.0f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var objectList = drawFront ? visibleObjectsFront : visibleObjectsBack;
|
var objectList = drawFront ? visibleObjectsFront : visibleObjectsBack;
|
||||||
@@ -113,19 +138,17 @@ namespace Barotrauma
|
|||||||
Vector2 camDiff = new Vector2(obj.Position.X, obj.Position.Y) - cam.WorldViewCenter;
|
Vector2 camDiff = new Vector2(obj.Position.X, obj.Position.Y) - cam.WorldViewCenter;
|
||||||
camDiff.Y = -camDiff.Y;
|
camDiff.Y = -camDiff.Y;
|
||||||
|
|
||||||
Sprite activeSprite = specular ? obj.SpecularSprite : obj.Sprite;
|
Sprite activeSprite = obj.Sprite;
|
||||||
activeSprite?.Draw(
|
activeSprite?.Draw(
|
||||||
spriteBatch,
|
spriteBatch,
|
||||||
new Vector2(obj.Position.X, -obj.Position.Y) - camDiff * obj.Position.Z / 10000.0f,
|
new Vector2(obj.Position.X, -obj.Position.Y) - camDiff * obj.Position.Z / 10000.0f,
|
||||||
Color.Lerp(Color.White, Level.Loaded.BackgroundTextureColor, obj.Position.Z / 5000.0f),
|
Color.Lerp(Color.White, Level.Loaded.BackgroundTextureColor, obj.Position.Z / 3000.0f),
|
||||||
activeSprite.Origin,
|
activeSprite.Origin,
|
||||||
obj.CurrentRotation,
|
obj.CurrentRotation,
|
||||||
obj.CurrentScale,
|
obj.CurrentScale,
|
||||||
SpriteEffects.None,
|
SpriteEffects.None,
|
||||||
z);
|
z);
|
||||||
|
|
||||||
if (specular) continue;
|
|
||||||
|
|
||||||
if (obj.ActivePrefab.DeformableSprite != null)
|
if (obj.ActivePrefab.DeformableSprite != null)
|
||||||
{
|
{
|
||||||
if (obj.CurrentSpriteDeformation != null)
|
if (obj.CurrentSpriteDeformation != null)
|
||||||
@@ -149,6 +172,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
GUI.DrawRectangle(spriteBatch, new Vector2(obj.Position.X, -obj.Position.Y), new Vector2(10.0f, 10.0f), GUI.Style.Red, true);
|
GUI.DrawRectangle(spriteBatch, new Vector2(obj.Position.X, -obj.Position.Y), new Vector2(10.0f, 10.0f), GUI.Style.Red, true);
|
||||||
|
|
||||||
|
if (obj.Triggers == null) { continue; }
|
||||||
foreach (LevelTrigger trigger in obj.Triggers)
|
foreach (LevelTrigger trigger in obj.Triggers)
|
||||||
{
|
{
|
||||||
if (trigger.PhysicsBody == null) continue;
|
if (trigger.PhysicsBody == null) continue;
|
||||||
|
|||||||
+25
-6
@@ -126,7 +126,6 @@ namespace Barotrauma
|
|||||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||||
{
|
{
|
||||||
case "childobject":
|
case "childobject":
|
||||||
case "lightsource":
|
|
||||||
subElement.Remove();
|
subElement.Remove();
|
||||||
break;
|
break;
|
||||||
case "deformablesprite":
|
case "deformablesprite":
|
||||||
@@ -141,11 +140,31 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (LightSourceParams lightSourceParams in LightSourceParams)
|
for (int i = 0; i < LightSourceParams.Count; i++)
|
||||||
{
|
{
|
||||||
var lightElement = new XElement("LightSource");
|
int elementIndex = 0;
|
||||||
SerializableProperty.SerializeProperties(lightSourceParams, lightElement);
|
bool wasSaved = false;
|
||||||
element.Add(lightElement);
|
foreach (XElement subElement in element.Elements().ToList())
|
||||||
|
{
|
||||||
|
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||||
|
{
|
||||||
|
case "lightsource":
|
||||||
|
if (elementIndex == i)
|
||||||
|
{
|
||||||
|
SerializableProperty.SerializeProperties(LightSourceParams[i], subElement);
|
||||||
|
wasSaved = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
elementIndex++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!wasSaved)
|
||||||
|
{
|
||||||
|
var lightElement = new XElement("LightSource");
|
||||||
|
SerializableProperty.SerializeProperties(LightSourceParams[i], lightElement);
|
||||||
|
element.Add(lightElement);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (ChildObject childObj in ChildObjects)
|
foreach (ChildObject childObj in ChildObjects)
|
||||||
@@ -162,7 +181,7 @@ namespace Barotrauma
|
|||||||
foreach (XElement subElement in element.Elements())
|
foreach (XElement subElement in element.Elements())
|
||||||
{
|
{
|
||||||
if (subElement.Name.ToString().Equals("overridecommonness", System.StringComparison.OrdinalIgnoreCase)
|
if (subElement.Name.ToString().Equals("overridecommonness", System.StringComparison.OrdinalIgnoreCase)
|
||||||
&& subElement.GetAttributeString("leveltype", "") == overrideCommonness.Key)
|
&& subElement.GetAttributeString("leveltype", "").Equals(overrideCommonness.Key, System.StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
subElement.Attribute("commonness").Value = overrideCommonness.Value.ToString("G", CultureInfo.InvariantCulture);
|
subElement.Attribute("commonness").Value = overrideCommonness.Value.ToString("G", CultureInfo.InvariantCulture);
|
||||||
elementFound = true;
|
elementFound = true;
|
||||||
|
|||||||
@@ -3,10 +3,68 @@ 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.Linq;
|
||||||
using Voronoi2;
|
using Voronoi2;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
|
class LevelWallVertexBuffer : IDisposable
|
||||||
|
{
|
||||||
|
public VertexBuffer WallEdgeBuffer, WallBuffer;
|
||||||
|
public readonly Texture2D WallTexture, EdgeTexture;
|
||||||
|
private VertexPositionColorTexture[] wallVertices;
|
||||||
|
private VertexPositionColorTexture[] wallEdgeVertices;
|
||||||
|
|
||||||
|
public bool IsDisposed
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LevelWallVertexBuffer(VertexPositionTexture[] wallVertices, VertexPositionTexture[] wallEdgeVertices, Texture2D wallTexture, Texture2D edgeTexture, Color color)
|
||||||
|
{
|
||||||
|
this.wallVertices = LevelRenderer.GetColoredVertices(wallVertices, color);
|
||||||
|
WallBuffer = new VertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, wallVertices.Length, BufferUsage.WriteOnly);
|
||||||
|
WallBuffer.SetData(this.wallVertices);
|
||||||
|
WallTexture = wallTexture;
|
||||||
|
|
||||||
|
this.wallEdgeVertices = LevelRenderer.GetColoredVertices(wallEdgeVertices, color);
|
||||||
|
WallEdgeBuffer = new VertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, wallEdgeVertices.Length, BufferUsage.WriteOnly);
|
||||||
|
WallEdgeBuffer.SetData(this.wallEdgeVertices);
|
||||||
|
EdgeTexture = edgeTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Append(VertexPositionTexture[] wallVertices, VertexPositionTexture[] wallEdgeVertices, Color color)
|
||||||
|
{
|
||||||
|
WallBuffer.Dispose();
|
||||||
|
WallBuffer = new VertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, this.wallVertices.Length + wallVertices.Length, BufferUsage.WriteOnly);
|
||||||
|
int originalWallVertexCount = this.wallVertices.Length;
|
||||||
|
Array.Resize(ref this.wallVertices, originalWallVertexCount + wallVertices.Length);
|
||||||
|
Array.Copy(LevelRenderer.GetColoredVertices(wallVertices, color), 0, this.wallVertices, originalWallVertexCount, wallVertices.Length);
|
||||||
|
WallBuffer.SetData(this.wallVertices);
|
||||||
|
|
||||||
|
WallEdgeBuffer.Dispose();
|
||||||
|
WallEdgeBuffer = new VertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, this.wallEdgeVertices.Length + wallEdgeVertices.Length, BufferUsage.WriteOnly);
|
||||||
|
int originalWallEdgeVertexCount = this.wallEdgeVertices.Length;
|
||||||
|
Array.Resize(ref this.wallEdgeVertices, originalWallEdgeVertexCount + wallEdgeVertices.Length);
|
||||||
|
Array.Copy(LevelRenderer.GetColoredVertices(wallEdgeVertices, color), 0, this.wallEdgeVertices, originalWallEdgeVertexCount, wallEdgeVertices.Length);
|
||||||
|
WallEdgeBuffer.SetData(this.wallEdgeVertices);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
IsDisposed = true;
|
||||||
|
WallEdgeBuffer?.Dispose();
|
||||||
|
WallBuffer?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class LevelRenderer : IDisposable
|
class LevelRenderer : IDisposable
|
||||||
{
|
{
|
||||||
private static BasicEffect wallEdgeEffect, wallCenterEffect;
|
private static BasicEffect wallEdgeEffect, wallCenterEffect;
|
||||||
@@ -15,11 +73,11 @@ namespace Barotrauma
|
|||||||
private Vector2 defaultDustVelocity;
|
private Vector2 defaultDustVelocity;
|
||||||
private Vector2 dustVelocity;
|
private Vector2 dustVelocity;
|
||||||
|
|
||||||
private RasterizerState cullNone;
|
private readonly RasterizerState cullNone;
|
||||||
|
|
||||||
private Level level;
|
private readonly Level level;
|
||||||
|
|
||||||
private VertexBuffer wallVertices, bodyVertices;
|
private readonly List<LevelWallVertexBuffer> vertexBuffers = new List<LevelWallVertexBuffer>();
|
||||||
|
|
||||||
public LevelRenderer(Level level)
|
public LevelRenderer(Level level)
|
||||||
{
|
{
|
||||||
@@ -68,6 +126,7 @@ namespace Barotrauma
|
|||||||
Vector2 currentDustVel = defaultDustVelocity;
|
Vector2 currentDustVel = defaultDustVelocity;
|
||||||
foreach (LevelObject levelObject in level.LevelObjectManager.GetVisibleObjects())
|
foreach (LevelObject levelObject in level.LevelObjectManager.GetVisibleObjects())
|
||||||
{
|
{
|
||||||
|
if (levelObject.Triggers == null) { continue; }
|
||||||
//use the largest water flow velocity of all the triggers
|
//use the largest water flow velocity of all the triggers
|
||||||
Vector2 objectMaxFlow = Vector2.Zero;
|
Vector2 objectMaxFlow = Vector2.Zero;
|
||||||
foreach (LevelTrigger trigger in levelObject.Triggers)
|
foreach (LevelTrigger trigger in levelObject.Triggers)
|
||||||
@@ -94,7 +153,6 @@ namespace Barotrauma
|
|||||||
while (dustOffset.Y <= -waterTextureSize.Y) dustOffset.Y += waterTextureSize.Y;
|
while (dustOffset.Y <= -waterTextureSize.Y) dustOffset.Y += waterTextureSize.Y;
|
||||||
while (dustOffset.Y >= waterTextureSize.Y) dustOffset.Y -= waterTextureSize.Y;
|
while (dustOffset.Y >= waterTextureSize.Y) dustOffset.Y -= waterTextureSize.Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static VertexPositionColorTexture[] GetColoredVertices(VertexPositionTexture[] vertices, Color color)
|
public static VertexPositionColorTexture[] GetColoredVertices(VertexPositionTexture[] vertices, Color color)
|
||||||
@@ -107,28 +165,17 @@ namespace Barotrauma
|
|||||||
return verts;
|
return verts;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetWallVertices(VertexPositionTexture[] vertices, Color color)
|
public void SetVertices(VertexPositionTexture[] wallVertices, VertexPositionTexture[] wallEdgeVertices, Texture2D wallTexture, Texture2D edgeTexture, Color color)
|
||||||
{
|
{
|
||||||
wallVertices = new VertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
|
var existingBuffer = vertexBuffers.Find(vb => vb.WallTexture == wallTexture && vb.EdgeTexture == edgeTexture);
|
||||||
wallVertices.SetData(GetColoredVertices(vertices, color));
|
if (existingBuffer != null)
|
||||||
}
|
{
|
||||||
|
existingBuffer.Append(wallVertices, wallEdgeVertices,color);
|
||||||
public void SetBodyVertices(VertexPositionTexture[] vertices, Color color)
|
}
|
||||||
{
|
else
|
||||||
bodyVertices = new VertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
|
{
|
||||||
bodyVertices.SetData(GetColoredVertices(vertices, color));
|
vertexBuffers.Add(new LevelWallVertexBuffer(wallVertices, wallEdgeVertices, wallTexture, edgeTexture, color));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetWallVertices(VertexPositionColorTexture[] vertices)
|
|
||||||
{
|
|
||||||
wallVertices = new VertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, vertices.Length,BufferUsage.WriteOnly);
|
|
||||||
wallVertices.SetData(vertices);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetBodyVertices(VertexPositionColorTexture[] vertices)
|
|
||||||
{
|
|
||||||
bodyVertices = new VertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
|
|
||||||
bodyVertices.SetData(vertices);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DrawBackground(SpriteBatch spriteBatch, Camera cam,
|
public void DrawBackground(SpriteBatch spriteBatch, Camera cam,
|
||||||
@@ -173,10 +220,13 @@ namespace Barotrauma
|
|||||||
SamplerState.LinearWrap, DepthStencilState.DepthRead, null, null,
|
SamplerState.LinearWrap, DepthStencilState.DepthRead, null, null,
|
||||||
cam.Transform);
|
cam.Transform);
|
||||||
|
|
||||||
if (backgroundSpriteManager != null) backgroundSpriteManager.DrawObjects(spriteBatch, cam, drawFront: false);
|
backgroundSpriteManager?.DrawObjects(spriteBatch, cam, drawFront: false);
|
||||||
if (backgroundCreatureManager != null) backgroundCreatureManager.Draw(spriteBatch, cam);
|
if (cam.Zoom > 0.05f)
|
||||||
|
{
|
||||||
|
backgroundCreatureManager?.Draw(spriteBatch, cam);
|
||||||
|
}
|
||||||
|
|
||||||
if (level.GenerationParams.WaterParticles != null)
|
if (level.GenerationParams.WaterParticles != null && cam.Zoom > 0.05f)
|
||||||
{
|
{
|
||||||
float textureScale = level.GenerationParams.WaterParticleScale;
|
float textureScale = level.GenerationParams.WaterParticleScale;
|
||||||
|
|
||||||
@@ -216,7 +266,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
|
|
||||||
RenderWalls(GameMain.Instance.GraphicsDevice, cam, specular: false);
|
RenderWalls(GameMain.Instance.GraphicsDevice, cam);
|
||||||
|
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred,
|
spriteBatch.Begin(SpriteSortMode.Deferred,
|
||||||
BlendState.NonPremultiplied,
|
BlendState.NonPremultiplied,
|
||||||
@@ -243,7 +293,8 @@ namespace Barotrauma
|
|||||||
foreach (GraphEdge edge in cell.Edges)
|
foreach (GraphEdge edge in cell.Edges)
|
||||||
{
|
{
|
||||||
GUI.DrawLine(spriteBatch, new Vector2(edge.Point1.X + cell.Translation.X, -(edge.Point1.Y + cell.Translation.Y)),
|
GUI.DrawLine(spriteBatch, new Vector2(edge.Point1.X + cell.Translation.X, -(edge.Point1.Y + cell.Translation.Y)),
|
||||||
new Vector2(edge.Point2.X + cell.Translation.X, -(edge.Point2.Y + cell.Translation.Y)), cell.Body == null ? Color.Cyan * 0.5f : Color.White);
|
new Vector2(edge.Point2.X + cell.Translation.X, -(edge.Point2.Y + cell.Translation.Y)), edge.NextToCave ? Color.Red : (cell.Body == null ? Color.Cyan * 0.5f : (edge.IsSolid ? Color.White : Color.Gray)),
|
||||||
|
width: edge.NextToCave ? 8 :1);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Vector2 point in cell.BodyVertices)
|
foreach (Vector2 point in cell.BodyVertices)
|
||||||
@@ -252,7 +303,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (List<Point> nodeList in level.SmallTunnels)
|
/*foreach (List<Point> nodeList in level.SmallTunnels)
|
||||||
{
|
{
|
||||||
for (int i = 1; i < nodeList.Count; i++)
|
for (int i = 1; i < nodeList.Count; i++)
|
||||||
{
|
{
|
||||||
@@ -261,7 +312,7 @@ namespace Barotrauma
|
|||||||
new Vector2(nodeList[i].X, -nodeList[i].Y),
|
new Vector2(nodeList[i].X, -nodeList[i].Y),
|
||||||
Color.Lerp(Color.Yellow, GUI.Style.Red, i / (float)nodeList.Count), 0, 10);
|
Color.Lerp(Color.Yellow, GUI.Style.Red, i / (float)nodeList.Count), 0, 10);
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
foreach (var ruin in level.Ruins)
|
foreach (var ruin in level.Ruins)
|
||||||
{
|
{
|
||||||
@@ -270,108 +321,142 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
Vector2 pos = new Vector2(0.0f, -level.Size.Y);
|
Vector2 pos = new Vector2(0.0f, -level.Size.Y);
|
||||||
|
|
||||||
if (cam.WorldView.Y >= -pos.Y - 1024)
|
if (cam.WorldView.Y >= -pos.Y - 1024)
|
||||||
{
|
{
|
||||||
pos.X = cam.WorldView.X -1024;
|
int topBarrierWidth = level.GenerationParams.WallEdgeSprite.Texture.Width;
|
||||||
int width = (int)(Math.Ceiling(cam.WorldView.Width / 1024 + 4.0f) * 1024);
|
int topBarrierHeight = level.GenerationParams.WallEdgeSprite.Texture.Height;
|
||||||
|
|
||||||
GUI.DrawRectangle(spriteBatch,new Rectangle(
|
pos.X = cam.WorldView.X - topBarrierWidth;
|
||||||
(int)(MathUtils.Round(pos.X, 1024)),
|
int width = (int)(Math.Ceiling(cam.WorldView.Width / 1024 + 4.0f) * topBarrierWidth);
|
||||||
|
|
||||||
|
GUI.DrawRectangle(spriteBatch, new Rectangle(
|
||||||
|
(int)MathUtils.Round(pos.X, topBarrierWidth),
|
||||||
-cam.WorldView.Y,
|
-cam.WorldView.Y,
|
||||||
width,
|
width,
|
||||||
(int)(cam.WorldView.Y + pos.Y) - 30),
|
(int)(cam.WorldView.Y + pos.Y) - 60),
|
||||||
Color.Black, true);
|
Color.Black, true);
|
||||||
|
|
||||||
spriteBatch.Draw(level.GenerationParams.WallEdgeSprite.Texture,
|
spriteBatch.Draw(level.GenerationParams.WallEdgeSprite.Texture,
|
||||||
new Rectangle((int)(MathUtils.Round(pos.X, 1024)), (int)pos.Y-1000, width, 1024),
|
new Rectangle((int)MathUtils.Round(pos.X, topBarrierWidth), (int)(pos.Y - topBarrierHeight + level.GenerationParams.WallEdgeExpandOutwardsAmount), width, topBarrierHeight),
|
||||||
new Rectangle(0, 0, width, -1024),
|
new Rectangle(0, 0, width, -topBarrierHeight),
|
||||||
level.BackgroundTextureColor, 0.0f,
|
GameMain.LightManager?.LightingEnabled ?? false ? GameMain.LightManager.AmbientLight : level.WallColor, 0.0f,
|
||||||
Vector2.Zero,
|
Vector2.Zero,
|
||||||
SpriteEffects.None, 0.0f);
|
SpriteEffects.None, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cam.WorldView.Y - cam.WorldView.Height < level.SeaFloorTopPos + 1024)
|
if (cam.WorldView.Y - cam.WorldView.Height < level.SeaFloorTopPos + 1024)
|
||||||
{
|
{
|
||||||
pos = new Vector2(cam.WorldView.X - 1024, -level.BottomPos);
|
int bottomBarrierWidth = level.GenerationParams.WallEdgeSprite.Texture.Width;
|
||||||
|
int bottomBarrierHeight = level.GenerationParams.WallEdgeSprite.Texture.Height;
|
||||||
int width = (int)(Math.Ceiling(cam.WorldView.Width / 1024 + 4.0f) * 1024);
|
pos = new Vector2(cam.WorldView.X - bottomBarrierWidth, -level.BottomPos);
|
||||||
|
int width = (int)(Math.Ceiling(cam.WorldView.Width / bottomBarrierWidth + 4.0f) * bottomBarrierWidth);
|
||||||
|
|
||||||
GUI.DrawRectangle(spriteBatch, new Rectangle(
|
GUI.DrawRectangle(spriteBatch, new Rectangle(
|
||||||
(int)(MathUtils.Round(pos.X, 1024)),
|
(int)(MathUtils.Round(pos.X, bottomBarrierWidth)),
|
||||||
(int)-(level.BottomPos - 30),
|
-(level.BottomPos - 60),
|
||||||
width,
|
width,
|
||||||
(int)(level.BottomPos - (cam.WorldView.Y - cam.WorldView.Height))),
|
level.BottomPos - (cam.WorldView.Y - cam.WorldView.Height)),
|
||||||
Color.Black, true);
|
Color.Black, true);
|
||||||
|
|
||||||
spriteBatch.Draw(level.GenerationParams.WallEdgeSprite.Texture,
|
spriteBatch.Draw(level.GenerationParams.WallEdgeSprite.Texture,
|
||||||
new Rectangle((int)(MathUtils.Round(pos.X, 1024)), (int)-level.BottomPos, width, 1024),
|
new Rectangle((int)MathUtils.Round(pos.X, bottomBarrierWidth), -level.BottomPos - (int)level.GenerationParams.WallEdgeExpandOutwardsAmount, width, bottomBarrierHeight),
|
||||||
new Rectangle(0, 0, width, -1024),
|
new Rectangle(0, 0, width, -bottomBarrierHeight),
|
||||||
level.BackgroundTextureColor, 0.0f,
|
GameMain.LightManager?.LightingEnabled ?? false ? GameMain.LightManager.AmbientLight : level.WallColor, 0.0f,
|
||||||
Vector2.Zero,
|
Vector2.Zero,
|
||||||
SpriteEffects.FlipVertically, 0.0f);
|
SpriteEffects.FlipVertically, 0.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void RenderWalls(GraphicsDevice graphicsDevice, Camera cam, bool specular)
|
public void RenderWalls(GraphicsDevice graphicsDevice, Camera cam)
|
||||||
{
|
{
|
||||||
if (wallVertices == null) return;
|
if (!vertexBuffers.Any()) { return; }
|
||||||
|
|
||||||
bool renderLevel = cam.WorldView.Y >= 0.0f;
|
var defaultRasterizerState = graphicsDevice.RasterizerState;
|
||||||
bool renderSeaFloor = cam.WorldView.Y - cam.WorldView.Height < level.SeaFloorTopPos + 1024;
|
|
||||||
|
|
||||||
if (!renderLevel && !renderSeaFloor) return;
|
|
||||||
|
|
||||||
Matrix transformMatrix = cam.ShaderTransform
|
Matrix transformMatrix = cam.ShaderTransform
|
||||||
* Matrix.CreateOrthographic(GameMain.GraphicsWidth, GameMain.GraphicsHeight, -1, 100) * 0.5f;
|
* Matrix.CreateOrthographic(GameMain.GraphicsWidth, GameMain.GraphicsHeight, -1, 100) * 0.5f;
|
||||||
|
|
||||||
wallEdgeEffect.Texture = specular && level.GenerationParams.WallEdgeSpriteSpecular != null ?
|
|
||||||
level.GenerationParams.WallEdgeSpriteSpecular.Texture :
|
|
||||||
level.GenerationParams.WallEdgeSprite.Texture;
|
|
||||||
wallEdgeEffect.World = transformMatrix;
|
|
||||||
wallCenterEffect.Texture = specular && level.GenerationParams.WallSpriteSpecular != null ?
|
|
||||||
level.GenerationParams.WallSpriteSpecular.Texture :
|
|
||||||
level.GenerationParams.WallSprite.Texture;
|
|
||||||
wallCenterEffect.World = transformMatrix;
|
|
||||||
|
|
||||||
graphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;
|
graphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;
|
||||||
wallCenterEffect.CurrentTechnique.Passes[0].Apply();
|
|
||||||
|
|
||||||
if (renderLevel)
|
|
||||||
{
|
|
||||||
graphicsDevice.SetVertexBuffer(bodyVertices);
|
|
||||||
graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (int)Math.Floor(bodyVertices.VertexCount / 3.0f));
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (LevelWall wall in level.ExtraWalls)
|
|
||||||
{
|
|
||||||
if (!renderSeaFloor && wall == level.SeaFloor) continue;
|
|
||||||
wallCenterEffect.World = wall.GetTransform() * transformMatrix;
|
|
||||||
wallCenterEffect.CurrentTechnique.Passes[0].Apply();
|
|
||||||
graphicsDevice.SetVertexBuffer(wall.BodyVertices);
|
|
||||||
graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (int)Math.Floor(wall.BodyVertices.VertexCount / 3.0f));
|
|
||||||
}
|
|
||||||
|
|
||||||
var defaultRasterizerState = graphicsDevice.RasterizerState;
|
|
||||||
graphicsDevice.RasterizerState = cullNone;
|
graphicsDevice.RasterizerState = cullNone;
|
||||||
wallEdgeEffect.World = transformMatrix;
|
|
||||||
wallEdgeEffect.CurrentTechnique.Passes[0].Apply();
|
|
||||||
|
|
||||||
if (renderLevel)
|
//render destructible walls
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
wallEdgeEffect.CurrentTechnique.Passes[0].Apply();
|
var wallList = i == 0 ? level.ExtraWalls : level.UnsyncedExtraWalls;
|
||||||
graphicsDevice.SetVertexBuffer(wallVertices);
|
foreach (LevelWall wall in wallList)
|
||||||
graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (int)Math.Floor(wallVertices.VertexCount / 3.0f));
|
{
|
||||||
|
if (!(wall is DestructibleLevelWall destructibleWall) || destructibleWall.Destroyed) { continue; }
|
||||||
|
|
||||||
|
wallCenterEffect.Texture = level.GenerationParams.DestructibleWallSprite?.Texture ?? level.GenerationParams.WallSprite.Texture;
|
||||||
|
wallCenterEffect.World = wall.GetTransform() * transformMatrix;
|
||||||
|
wallCenterEffect.Alpha = wall.Alpha;
|
||||||
|
wallCenterEffect.CurrentTechnique.Passes[0].Apply();
|
||||||
|
graphicsDevice.SetVertexBuffer(wall.WallBuffer);
|
||||||
|
graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (int)Math.Floor(wall.WallBuffer.VertexCount / 3.0f));
|
||||||
|
|
||||||
|
wallEdgeEffect.Texture = level.GenerationParams.DestructibleWallEdgeSprite?.Texture ?? level.GenerationParams.WallEdgeSprite.Texture;
|
||||||
|
wallEdgeEffect.World = wall.GetTransform() * transformMatrix;
|
||||||
|
wallEdgeEffect.Alpha = wall.Alpha;
|
||||||
|
wallEdgeEffect.CurrentTechnique.Passes[0].Apply();
|
||||||
|
graphicsDevice.SetVertexBuffer(wall.WallEdgeBuffer);
|
||||||
|
graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (int)Math.Floor(wall.WallEdgeBuffer.VertexCount / 3.0f));
|
||||||
|
|
||||||
|
if (destructibleWall.Damage <= 0.0f) { continue; }
|
||||||
|
wallEdgeEffect.Texture = level.GenerationParams.WallSpriteDestroyed.Texture;
|
||||||
|
wallEdgeEffect.Alpha = MathHelper.Lerp(0.2f, 1.0f, destructibleWall.Damage / destructibleWall.MaxHealth) * wall.Alpha;
|
||||||
|
wallEdgeEffect.World = wall.GetTransform() * transformMatrix;
|
||||||
|
wallEdgeEffect.CurrentTechnique.Passes[0].Apply();
|
||||||
|
graphicsDevice.SetVertexBuffer(wall.WallEdgeBuffer);
|
||||||
|
graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (int)Math.Floor(wall.WallEdgeBuffer.VertexCount / 3.0f));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
foreach (LevelWall wall in level.ExtraWalls)
|
|
||||||
|
wallEdgeEffect.Alpha = 1.0f;
|
||||||
|
wallCenterEffect.Alpha = 1.0f;
|
||||||
|
|
||||||
|
wallCenterEffect.World = transformMatrix;
|
||||||
|
wallEdgeEffect.World = transformMatrix;
|
||||||
|
|
||||||
|
//render static walls
|
||||||
|
foreach (var vertexBuffer in vertexBuffers)
|
||||||
{
|
{
|
||||||
if (!renderSeaFloor && wall == level.SeaFloor) continue;
|
wallCenterEffect.Texture = vertexBuffer.WallTexture;
|
||||||
wallEdgeEffect.World = wall.GetTransform() * transformMatrix;
|
wallCenterEffect.CurrentTechnique.Passes[0].Apply();
|
||||||
|
graphicsDevice.SetVertexBuffer(vertexBuffer.WallBuffer);
|
||||||
|
graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (int)Math.Floor(vertexBuffer.WallBuffer.VertexCount / 3.0f));
|
||||||
|
|
||||||
|
wallEdgeEffect.Texture = vertexBuffer.EdgeTexture;
|
||||||
wallEdgeEffect.CurrentTechnique.Passes[0].Apply();
|
wallEdgeEffect.CurrentTechnique.Passes[0].Apply();
|
||||||
graphicsDevice.SetVertexBuffer(wall.WallVertices);
|
graphicsDevice.SetVertexBuffer(vertexBuffer.WallEdgeBuffer);
|
||||||
graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (int)Math.Floor(wall.WallVertices.VertexCount / 3.0f));
|
graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (int)Math.Floor(vertexBuffer.WallEdgeBuffer.VertexCount / 3.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wallCenterEffect.Texture = level.GenerationParams.WallSprite.Texture;
|
||||||
|
wallEdgeEffect.Texture = level.GenerationParams.WallEdgeSprite.Texture;
|
||||||
|
|
||||||
|
//render non-destructible extra walls
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
var wallList = i == 0 ? level.ExtraWalls : level.UnsyncedExtraWalls;
|
||||||
|
foreach (LevelWall wall in wallList)
|
||||||
|
{
|
||||||
|
if (wall is DestructibleLevelWall) { continue; }
|
||||||
|
//TODO: use LevelWallVertexBuffers for extra walls as well
|
||||||
|
wallCenterEffect.World = wall.GetTransform() * transformMatrix;
|
||||||
|
wallCenterEffect.Alpha = wall.Alpha;
|
||||||
|
wallCenterEffect.CurrentTechnique.Passes[0].Apply();
|
||||||
|
graphicsDevice.SetVertexBuffer(wall.WallBuffer);
|
||||||
|
graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (int)Math.Floor(wall.WallBuffer.VertexCount / 3.0f));
|
||||||
|
|
||||||
|
wallEdgeEffect.World = wall.GetTransform() * transformMatrix;
|
||||||
|
wallEdgeEffect.Alpha = wall.Alpha;
|
||||||
|
wallEdgeEffect.CurrentTechnique.Passes[0].Apply();
|
||||||
|
graphicsDevice.SetVertexBuffer(wall.WallEdgeBuffer);
|
||||||
|
graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (int)Math.Floor(wall.WallEdgeBuffer.VertexCount / 3.0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
graphicsDevice.RasterizerState = defaultRasterizerState;
|
graphicsDevice.RasterizerState = defaultRasterizerState;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,8 +468,11 @@ namespace Barotrauma
|
|||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (wallVertices != null) wallVertices.Dispose();
|
foreach (var vertexBuffer in vertexBuffers)
|
||||||
if (bodyVertices != null) bodyVertices.Dispose();
|
{
|
||||||
|
vertexBuffer.Dispose();
|
||||||
|
}
|
||||||
|
vertexBuffers.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,55 +2,44 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
partial class LevelWall : IDisposable
|
partial class LevelWall : IDisposable
|
||||||
{
|
{
|
||||||
private VertexBuffer wallVertices, bodyVertices;
|
public LevelWallVertexBuffer VertexBuffer { get; private set; }
|
||||||
|
|
||||||
public VertexBuffer WallVertices
|
public VertexBuffer WallBuffer { get { return VertexBuffer.WallBuffer; } }
|
||||||
{
|
|
||||||
get { return wallVertices; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public VertexBuffer BodyVertices
|
public VertexBuffer WallEdgeBuffer { get { return VertexBuffer.WallEdgeBuffer; } }
|
||||||
{
|
|
||||||
get { return bodyVertices; }
|
public virtual float Alpha => 1.0f;
|
||||||
}
|
|
||||||
|
|
||||||
public Matrix GetTransform()
|
public Matrix GetTransform()
|
||||||
{
|
{
|
||||||
return body.BodyType == BodyType.Static ?
|
return Body.FixedRotation ?
|
||||||
Matrix.Identity :
|
Matrix.CreateTranslation(new Vector3(ConvertUnits.ToDisplayUnits(Body.Position), 0.0f)) :
|
||||||
Matrix.CreateRotationZ(body.Rotation) *
|
Matrix.CreateRotationZ(Body.Rotation) *
|
||||||
Matrix.CreateTranslation(new Vector3(ConvertUnits.ToDisplayUnits(body.Position), 0.0f));
|
Matrix.CreateTranslation(new Vector3(ConvertUnits.ToDisplayUnits(Body.Position), 0.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetWallVertices(VertexPositionTexture[] vertices, Color color)
|
public void SetWallVertices(VertexPositionTexture[] wallVertices, VertexPositionTexture[] wallEdgeVertices, Texture2D wallTexture, Texture2D edgeTexture, Color color)
|
||||||
{
|
{
|
||||||
wallVertices = new VertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
|
if (VertexBuffer != null && !VertexBuffer.IsDisposed) { VertexBuffer.Dispose(); }
|
||||||
wallVertices.SetData(LevelRenderer.GetColoredVertices(vertices, color));
|
VertexBuffer = new LevelWallVertexBuffer(wallVertices, wallEdgeVertices, wallTexture, edgeTexture, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetBodyVertices(VertexPositionTexture[] vertices, Color color)
|
public void GenerateVertices()
|
||||||
{
|
{
|
||||||
bodyVertices = new VertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
|
float zCoord = this is DestructibleLevelWall ? Rand.Range(0.9f, 1.0f) : 0.9f;
|
||||||
bodyVertices.SetData(LevelRenderer.GetColoredVertices(vertices, color));
|
List<VertexPositionTexture> wallVertices = CaveGenerator.GenerateWallVertices(triangles, level.GenerationParams, zCoord);
|
||||||
}
|
SetWallVertices(
|
||||||
|
wallVertices.ToArray(),
|
||||||
public void SetWallVertices(VertexPositionColorTexture[] vertices)
|
CaveGenerator.GenerateWallEdgeVertices(Cells, level, zCoord).ToArray(),
|
||||||
{
|
level.GenerationParams.WallSprite.Texture,
|
||||||
if (wallVertices != null && !wallVertices.IsDisposed) wallVertices.Dispose();
|
level.GenerationParams.WallEdgeSprite.Texture,
|
||||||
wallVertices = new VertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
|
color);
|
||||||
wallVertices.SetData(vertices);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetBodyVertices(VertexPositionColorTexture[] vertices)
|
|
||||||
{
|
|
||||||
if (bodyVertices != null && !bodyVertices.IsDisposed) bodyVertices.Dispose();
|
|
||||||
bodyVertices = new VertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
|
|
||||||
bodyVertices.SetData(vertices);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -151,7 +151,16 @@ namespace Barotrauma.Lights
|
|||||||
|
|
||||||
private readonly List<LightSource> activeLights = new List<LightSource>(capacity: 100);
|
private readonly List<LightSource> activeLights = new List<LightSource>(capacity: 100);
|
||||||
|
|
||||||
public void UpdateLightMap(GraphicsDevice graphics, SpriteBatch spriteBatch, Camera cam, RenderTarget2D backgroundObstructor = null)
|
public void Update(float deltaTime)
|
||||||
|
{
|
||||||
|
foreach (LightSource light in lights)
|
||||||
|
{
|
||||||
|
if (!light.Enabled) { continue; }
|
||||||
|
light.Update(deltaTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RenderLightMap(GraphicsDevice graphics, SpriteBatch spriteBatch, Camera cam, RenderTarget2D backgroundObstructor = null)
|
||||||
{
|
{
|
||||||
if (!LightingEnabled) { return; }
|
if (!LightingEnabled) { return; }
|
||||||
|
|
||||||
@@ -174,7 +183,7 @@ namespace Barotrauma.Lights
|
|||||||
foreach (LightSource light in lights)
|
foreach (LightSource light in lights)
|
||||||
{
|
{
|
||||||
if (!light.Enabled) { continue; }
|
if (!light.Enabled) { continue; }
|
||||||
if ((light.Color.A < 1 || light.Range < 1.0f) && !light.LightSourceParams.OverrideLightSpriteAlpha.HasValue) { continue; }
|
if ((light.Color.A < 1 || light.Range < 1.0f || light.CurrentBrightness <= 0.0f) && !light.LightSourceParams.OverrideLightSpriteAlpha.HasValue) { continue; }
|
||||||
if (light.ParentBody != null)
|
if (light.ParentBody != null)
|
||||||
{
|
{
|
||||||
light.Position = light.ParentBody.DrawPosition;
|
light.Position = light.ParentBody.DrawPosition;
|
||||||
@@ -205,7 +214,7 @@ namespace Barotrauma.Lights
|
|||||||
{
|
{
|
||||||
if (light.IsBackground) { continue; }
|
if (light.IsBackground) { continue; }
|
||||||
//draw limb lights at this point, because they were skipped over previously to prevent them from being obstructed
|
//draw limb lights at this point, because they were skipped over previously to prevent them from being obstructed
|
||||||
if (light.ParentBody?.UserData is Limb) { light.DrawSprite(spriteBatch, cam); }
|
if (light.ParentBody?.UserData is Limb limb && !limb.Hide) { light.DrawSprite(spriteBatch, cam); }
|
||||||
}
|
}
|
||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
|
|
||||||
@@ -215,6 +224,7 @@ namespace Barotrauma.Lights
|
|||||||
graphics.Clear(AmbientLight);
|
graphics.Clear(AmbientLight);
|
||||||
graphics.BlendState = BlendState.Additive;
|
graphics.BlendState = BlendState.Additive;
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, transformMatrix: spriteBatchTransform);
|
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, transformMatrix: spriteBatchTransform);
|
||||||
|
Level.Loaded?.BackgroundCreatureManager?.DrawLights(spriteBatch, cam);
|
||||||
foreach (LightSource light in activeLights)
|
foreach (LightSource light in activeLights)
|
||||||
{
|
{
|
||||||
if (!light.IsBackground) { continue; }
|
if (!light.IsBackground) { continue; }
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
|
||||||
|
|
||||||
namespace Barotrauma.Lights
|
namespace Barotrauma.Lights
|
||||||
{
|
{
|
||||||
class LightSourceParams : ISerializableEntity
|
class LightSourceParams : ISerializableEntity
|
||||||
@@ -33,7 +32,7 @@ namespace Barotrauma.Lights
|
|||||||
get { return range; }
|
get { return range; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
range = MathHelper.Clamp(value, 0.0f, 2048.0f);
|
range = MathHelper.Clamp(value, 0.0f, 4096.0f);
|
||||||
TextureRange = range;
|
TextureRange = range;
|
||||||
if (OverrideLightTexture != null)
|
if (OverrideLightTexture != null)
|
||||||
{
|
{
|
||||||
@@ -50,6 +49,62 @@ namespace Barotrauma.Lights
|
|||||||
[Serialize("0, 0", true), Editable(ValueStep = 1, DecimalCount = 1, MinValueFloat = -1000f, MaxValueFloat = 1000f)]
|
[Serialize("0, 0", true), Editable(ValueStep = 1, DecimalCount = 1, MinValueFloat = -1000f, MaxValueFloat = 1000f)]
|
||||||
public Vector2 Offset { get; set; }
|
public Vector2 Offset { get; set; }
|
||||||
|
|
||||||
|
[Serialize(0f, true), Editable(MinValueFloat = -360, MaxValueFloat = 360, ValueStep = 1, DecimalCount = 0)]
|
||||||
|
public float Rotation { get; set; }
|
||||||
|
|
||||||
|
public Vector2 GetOffset() => Vector2.Transform(Offset, Matrix.CreateRotationZ(Rotation));
|
||||||
|
|
||||||
|
private float flicker;
|
||||||
|
[Editable, Serialize(0.0f, false, description: "How heavily the light flickers. 0 = no flickering, 1 = the light will alternate between completely dark and full brightness.")]
|
||||||
|
public float Flicker
|
||||||
|
{
|
||||||
|
get { return flicker; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
flicker = MathHelper.Clamp(value, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Editable, Serialize(1.0f, false, description: "How fast the light flickers.")]
|
||||||
|
public float FlickerSpeed
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
private float pulseFrequency;
|
||||||
|
[Editable, Serialize(0.0f, true, description: "How rapidly the light pulsates (in Hz). 0 = no blinking.")]
|
||||||
|
public float PulseFrequency
|
||||||
|
{
|
||||||
|
get { return pulseFrequency; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
pulseFrequency = MathHelper.Clamp(value, 0.0f, 60.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private float pulseAmount;
|
||||||
|
[Editable(MinValueFloat = 0.0f, MaxValueFloat = 1.0f, DecimalCount = 2), Serialize(0.0f, true, description: "How much light pulsates (in Hz). 0 = not at all, 1 = alternates between full brightness and off.")]
|
||||||
|
public float PulseAmount
|
||||||
|
{
|
||||||
|
get { return pulseAmount; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
pulseAmount = MathHelper.Clamp(value, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private float blinkFrequency;
|
||||||
|
[Editable, Serialize(0.0f, true, description: "How rapidly the light blinks on and off (in Hz). 0 = no blinking.")]
|
||||||
|
public float BlinkFrequency
|
||||||
|
{
|
||||||
|
get { return blinkFrequency; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
blinkFrequency = MathHelper.Clamp(value, 0.0f, 60.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public float TextureRange
|
public float TextureRange
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
@@ -88,6 +143,7 @@ namespace Barotrauma.Lights
|
|||||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||||
{
|
{
|
||||||
case "sprite":
|
case "sprite":
|
||||||
|
case "lightsprite":
|
||||||
{
|
{
|
||||||
LightSprite = new Sprite(subElement);
|
LightSprite = new Sprite(subElement);
|
||||||
float spriteAlpha = subElement.GetAttributeFloat("alpha", -1.0f);
|
float spriteAlpha = subElement.GetAttributeFloat("alpha", -1.0f);
|
||||||
@@ -144,6 +200,8 @@ namespace Barotrauma.Lights
|
|||||||
|
|
||||||
private static Texture2D lightTexture;
|
private static Texture2D lightTexture;
|
||||||
|
|
||||||
|
private float blinkTimer, flickerState, pulseState;
|
||||||
|
|
||||||
private VertexPositionColorTexture[] vertices;
|
private VertexPositionColorTexture[] vertices;
|
||||||
private short[] indices;
|
private short[] indices;
|
||||||
|
|
||||||
@@ -297,6 +355,12 @@ namespace Barotrauma.Lights
|
|||||||
set { lightSourceParams.Color = value; }
|
set { lightSourceParams.Color = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float CurrentBrightness
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
public float Range
|
public float Range
|
||||||
{
|
{
|
||||||
get { return lightSourceParams.Range; }
|
get { return lightSourceParams.Range; }
|
||||||
@@ -402,7 +466,41 @@ namespace Barotrauma.Lights
|
|||||||
texture = LightTexture;
|
texture = LightTexture;
|
||||||
diffToSub = new Dictionary<Submarine, Vector2>();
|
diffToSub = new Dictionary<Submarine, Vector2>();
|
||||||
if (addLight) { GameMain.LightManager.AddLight(this); }
|
if (addLight) { GameMain.LightManager.AddLight(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(float deltaTime)
|
||||||
|
{
|
||||||
|
if (lightSourceParams.BlinkFrequency > 0.0f)
|
||||||
|
{
|
||||||
|
blinkTimer = (blinkTimer + deltaTime * lightSourceParams.BlinkFrequency) % 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lightSourceParams.PulseFrequency > 0.0f)
|
||||||
|
{
|
||||||
|
pulseState = (pulseState + deltaTime * lightSourceParams.PulseFrequency) % 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (blinkTimer > 0.5f)
|
||||||
|
{
|
||||||
|
CurrentBrightness = 0.0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float flicker = 0.0f;
|
||||||
|
float pulse = 0.0f;
|
||||||
|
if (lightSourceParams.Flicker > 0.0f)
|
||||||
|
{
|
||||||
|
flickerState += deltaTime * lightSourceParams.FlickerSpeed;
|
||||||
|
flickerState %= 255;
|
||||||
|
flicker = PerlinNoise.GetPerlin(flickerState, flickerState * 0.5f) * lightSourceParams.Flicker;
|
||||||
|
}
|
||||||
|
if (lightSourceParams.PulseFrequency > 0.0f && lightSourceParams.PulseAmount > 0.0f)
|
||||||
|
{
|
||||||
|
//oscillate between 0-1
|
||||||
|
pulse = (float)(Math.Sin(pulseState * MathHelper.TwoPi) + 1.0f) / 2.0f * lightSourceParams.PulseAmount;
|
||||||
|
}
|
||||||
|
CurrentBrightness = (1.0f - flicker) * (1.0f - pulse);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -508,13 +606,12 @@ namespace Barotrauma.Lights
|
|||||||
|
|
||||||
//recalculate vertices if the subs have moved > 5 px relative to each other
|
//recalculate vertices if the subs have moved > 5 px relative to each other
|
||||||
Vector2 diff = ParentSub.WorldPosition - sub.WorldPosition;
|
Vector2 diff = ParentSub.WorldPosition - sub.WorldPosition;
|
||||||
Vector2 prevDiff;
|
if (!diffToSub.TryGetValue(sub, out Vector2 prevDiff))
|
||||||
if (!diffToSub.TryGetValue(sub, out prevDiff))
|
|
||||||
{
|
{
|
||||||
diffToSub.Add(sub, diff);
|
diffToSub.Add(sub, diff);
|
||||||
NeedsRecalculation = true;
|
NeedsRecalculation = true;
|
||||||
}
|
}
|
||||||
else if (Vector2.DistanceSquared(diff, prevDiff) > 5.0f*5.0f)
|
else if (Vector2.DistanceSquared(diff, prevDiff) > 5.0f * 5.0f)
|
||||||
{
|
{
|
||||||
diffToSub[sub] = diff;
|
diffToSub[sub] = diff;
|
||||||
NeedsRecalculation = true;
|
NeedsRecalculation = true;
|
||||||
@@ -884,7 +981,12 @@ namespace Barotrauma.Lights
|
|||||||
overrideTextureDims = new Vector2(OverrideLightTexture.SourceRect.Width, OverrideLightTexture.SourceRect.Height);
|
overrideTextureDims = new Vector2(OverrideLightTexture.SourceRect.Width, OverrideLightTexture.SourceRect.Height);
|
||||||
|
|
||||||
Vector2 origin = OverrideLightTextureOrigin;
|
Vector2 origin = OverrideLightTextureOrigin;
|
||||||
if (LightSpriteEffect == SpriteEffects.FlipHorizontally) { origin.X = OverrideLightTexture.SourceRect.Width - origin.X; }
|
if (LightSpriteEffect == SpriteEffects.FlipHorizontally)
|
||||||
|
{
|
||||||
|
origin.X = OverrideLightTexture.SourceRect.Width - origin.X;
|
||||||
|
cosAngle = -cosAngle;
|
||||||
|
sinAngle = -sinAngle;
|
||||||
|
}
|
||||||
if (LightSpriteEffect == SpriteEffects.FlipVertically) { origin.Y = OverrideLightTexture.SourceRect.Height - origin.Y; }
|
if (LightSpriteEffect == SpriteEffects.FlipVertically) { origin.Y = OverrideLightTexture.SourceRect.Height - origin.Y; }
|
||||||
uvOffset = (origin / overrideTextureDims) - new Vector2(0.5f, 0.5f);
|
uvOffset = (origin / overrideTextureDims) - new Vector2(0.5f, 0.5f);
|
||||||
}
|
}
|
||||||
@@ -1021,7 +1123,7 @@ namespace Barotrauma.Lights
|
|||||||
lightVolumeBuffer.SetData<VertexPositionColorTexture>(vertices, 0, vertexCount);
|
lightVolumeBuffer.SetData<VertexPositionColorTexture>(vertices, 0, vertexCount);
|
||||||
lightVolumeIndexBuffer.SetData<short>(indices, 0, indexCount);
|
lightVolumeIndexBuffer.SetData<short>(indices, 0, indexCount);
|
||||||
|
|
||||||
Vector2 GetUV(Vector2 vert, SpriteEffects effects)
|
static Vector2 GetUV(Vector2 vert, SpriteEffects effects)
|
||||||
{
|
{
|
||||||
if (effects == SpriteEffects.FlipHorizontally)
|
if (effects == SpriteEffects.FlipHorizontally)
|
||||||
{
|
{
|
||||||
@@ -1098,7 +1200,7 @@ namespace Barotrauma.Lights
|
|||||||
|
|
||||||
if (DeformableLightSprite != null)
|
if (DeformableLightSprite != null)
|
||||||
{
|
{
|
||||||
Vector2 origin = DeformableLightSprite.Origin + LightSourceParams.Offset;
|
Vector2 origin = DeformableLightSprite.Origin + LightSourceParams.GetOffset();
|
||||||
Vector2 drawPos = position;
|
Vector2 drawPos = position;
|
||||||
if (ParentSub != null)
|
if (ParentSub != null)
|
||||||
{
|
{
|
||||||
@@ -1115,14 +1217,14 @@ namespace Barotrauma.Lights
|
|||||||
|
|
||||||
DeformableLightSprite.Draw(
|
DeformableLightSprite.Draw(
|
||||||
cam, new Vector3(drawPos, 0.0f),
|
cam, new Vector3(drawPos, 0.0f),
|
||||||
origin, -Rotation, SpriteScale,
|
origin, -Rotation + MathHelper.ToRadians(LightSourceParams.Rotation), SpriteScale,
|
||||||
new Color(Color, lightSourceParams.OverrideLightSpriteAlpha ?? Color.A / 255.0f),
|
new Color(Color, (lightSourceParams.OverrideLightSpriteAlpha ?? Color.A / 255.0f) * CurrentBrightness),
|
||||||
LightSpriteEffect == SpriteEffects.FlipVertically);
|
LightSpriteEffect == SpriteEffects.FlipVertically);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LightSprite != null)
|
if (LightSprite != null)
|
||||||
{
|
{
|
||||||
Vector2 origin = LightSprite.Origin + LightSourceParams.Offset;
|
Vector2 origin = LightSprite.Origin + LightSourceParams.GetOffset();
|
||||||
if ((LightSpriteEffect & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally)
|
if ((LightSpriteEffect & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally)
|
||||||
{
|
{
|
||||||
origin.X = LightSprite.SourceRect.Width - origin.X;
|
origin.X = LightSprite.SourceRect.Width - origin.X;
|
||||||
@@ -1141,8 +1243,8 @@ namespace Barotrauma.Lights
|
|||||||
|
|
||||||
LightSprite.Draw(
|
LightSprite.Draw(
|
||||||
spriteBatch, drawPos,
|
spriteBatch, drawPos,
|
||||||
new Color(Color, lightSourceParams.OverrideLightSpriteAlpha ?? Color.A / 255.0f),
|
new Color(Color, (lightSourceParams.OverrideLightSpriteAlpha ?? Color.A / 255.0f) * CurrentBrightness),
|
||||||
origin, -Rotation, SpriteScale, LightSpriteEffect);
|
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)
|
||||||
@@ -1185,7 +1287,7 @@ namespace Barotrauma.Lights
|
|||||||
|
|
||||||
public void DrawLightVolume(SpriteBatch spriteBatch, BasicEffect lightEffect, Matrix transform)
|
public void DrawLightVolume(SpriteBatch spriteBatch, BasicEffect lightEffect, Matrix transform)
|
||||||
{
|
{
|
||||||
if (Range < 1.0f || Color.A < 1) { return; }
|
if (Range < 1.0f || Color.A < 1 || CurrentBrightness <= 0.0f) { return; }
|
||||||
|
|
||||||
if (CastShadows)
|
if (CastShadows)
|
||||||
{
|
{
|
||||||
@@ -1207,7 +1309,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, -rotation, center, scale, SpriteEffects.None, 1);
|
spriteBatch.Draw(currentTexture, drawPos, null, Color.Multiply(CurrentBrightness), -rotation, center, scale, SpriteEffects.None, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1229,7 +1331,7 @@ namespace Barotrauma.Lights
|
|||||||
|
|
||||||
if (vertexCount == 0) { return; }
|
if (vertexCount == 0) { return; }
|
||||||
|
|
||||||
lightEffect.DiffuseColor = (new Vector3(Color.R, Color.G, Color.B) * (Color.A / 255.0f)) / 255.0f;
|
lightEffect.DiffuseColor = (new Vector3(Color.R, Color.G, Color.B) * (Color.A / 255.0f * CurrentBrightness)) / 255.0f;
|
||||||
if (OverrideLightTexture != null)
|
if (OverrideLightTexture != null)
|
||||||
{
|
{
|
||||||
lightEffect.Texture = OverrideLightTexture.Texture;
|
lightEffect.Texture = OverrideLightTexture.Texture;
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ namespace Barotrauma
|
|||||||
private Sprite[,] mapTiles;
|
private Sprite[,] mapTiles;
|
||||||
private bool[,] tileDiscovered;
|
private bool[,] tileDiscovered;
|
||||||
|
|
||||||
|
private Pair<Rectangle, string> connectionTooltip;
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
private GUIComponent editor;
|
private GUIComponent editor;
|
||||||
|
|
||||||
@@ -410,6 +412,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void Draw(SpriteBatch spriteBatch, GUICustomComponent mapContainer)
|
public void Draw(SpriteBatch spriteBatch, GUICustomComponent mapContainer)
|
||||||
{
|
{
|
||||||
|
connectionTooltip = null;
|
||||||
|
|
||||||
Rectangle rect = mapContainer.Rect;
|
Rectangle rect = mapContainer.Rect;
|
||||||
|
|
||||||
Vector2 viewSize = new Vector2(rect.Width / zoom, rect.Height / zoom);
|
Vector2 viewSize = new Vector2(rect.Width / zoom, rect.Height / zoom);
|
||||||
@@ -639,6 +643,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
GUIComponent.DrawToolTip(spriteBatch, tooltip.Second, tooltip.First);
|
GUIComponent.DrawToolTip(spriteBatch, tooltip.Second, tooltip.First);
|
||||||
}
|
}
|
||||||
|
if (connectionTooltip != null)
|
||||||
|
{
|
||||||
|
GUIComponent.DrawToolTip(spriteBatch, connectionTooltip.Second, connectionTooltip.First);
|
||||||
|
}
|
||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
GameMain.Instance.GraphicsDevice.ScissorRectangle = prevScissorRect;
|
GameMain.Instance.GraphicsDevice.ScissorRectangle = prevScissorRect;
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
|
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
|
||||||
@@ -689,12 +697,16 @@ namespace Barotrauma
|
|||||||
int startIndex = connection.CrackSegments.Count > 2 ? 1 : 0;
|
int startIndex = connection.CrackSegments.Count > 2 ? 1 : 0;
|
||||||
int endIndex = connection.CrackSegments.Count > 2 ? connection.CrackSegments.Count - 1 : connection.CrackSegments.Count;
|
int endIndex = connection.CrackSegments.Count > 2 ? connection.CrackSegments.Count - 1 : connection.CrackSegments.Count;
|
||||||
|
|
||||||
|
Vector2? connectionStart = null;
|
||||||
|
Vector2? connectionEnd = null;
|
||||||
for (int i = startIndex; i < endIndex; i++)
|
for (int i = startIndex; i < endIndex; i++)
|
||||||
{
|
{
|
||||||
var segment = connection.CrackSegments[i];
|
var segment = connection.CrackSegments[i];
|
||||||
|
|
||||||
Vector2 start = rectCenter + (segment[0] + viewOffset) * zoom;
|
Vector2 start = rectCenter + (segment[0] + viewOffset) * zoom;
|
||||||
Vector2 end = rectCenter + (segment[1] + viewOffset) * zoom;
|
if (!connectionStart.HasValue) { connectionStart = start; }
|
||||||
|
Vector2 end = rectCenter + (segment[1] + viewOffset) * zoom;
|
||||||
|
connectionEnd = end;
|
||||||
|
|
||||||
if (!viewArea.Contains(start) && !viewArea.Contains(end))
|
if (!viewArea.Contains(start) && !viewArea.Contains(end))
|
||||||
{
|
{
|
||||||
@@ -734,6 +746,40 @@ namespace Barotrauma
|
|||||||
connectionSprite.SourceRect, connectionColor * a, MathUtils.VectorToAngle(end - start),
|
connectionSprite.SourceRect, connectionColor * a, MathUtils.VectorToAngle(end - start),
|
||||||
new Vector2(0, connectionSprite.size.Y / 2), SpriteEffects.None, 0.01f);
|
new Vector2(0, connectionSprite.size.Y / 2), SpriteEffects.None, 0.01f);
|
||||||
}
|
}
|
||||||
|
if (connectionStart.HasValue && connectionEnd.HasValue)
|
||||||
|
{
|
||||||
|
GUIComponentStyle crushDepthWarningIconStyle = null;
|
||||||
|
string tooltip = null;
|
||||||
|
if (connection.LevelData.InitialDepth * Physics.DisplayToRealWorldRatio > connection.LevelData.RealWorldCrushDepth)
|
||||||
|
{
|
||||||
|
crushDepthWarningIconStyle = GUI.Style.GetComponentStyle("CrushDepthWarningHighIcon");
|
||||||
|
tooltip = "crushdepthwarninghigh";
|
||||||
|
}
|
||||||
|
else if ((connection.LevelData.InitialDepth + connection.LevelData.Size.Y) * Physics.DisplayToRealWorldRatio > connection.LevelData.RealWorldCrushDepth)
|
||||||
|
{
|
||||||
|
crushDepthWarningIconStyle = GUI.Style.GetComponentStyle("CrushDepthWarningLowIcon");
|
||||||
|
tooltip = "crushdepthwarninglow";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (crushDepthWarningIconStyle != null)
|
||||||
|
{
|
||||||
|
Vector2 iconPos = (connectionStart.Value + connectionEnd.Value) / 2;
|
||||||
|
float iconSize = 32.0f * GUI.Scale;
|
||||||
|
bool mouseOn = HighlightedLocation == null && Vector2.DistanceSquared(iconPos, PlayerInput.MousePosition) < iconSize * iconSize;
|
||||||
|
Sprite crushDepthWarningIcon = crushDepthWarningIconStyle.GetDefaultSprite();
|
||||||
|
crushDepthWarningIcon.Draw(spriteBatch, iconPos,
|
||||||
|
mouseOn ? crushDepthWarningIconStyle.HoverColor : crushDepthWarningIconStyle.Color,
|
||||||
|
scale: iconSize / crushDepthWarningIcon.size.X);
|
||||||
|
if (mouseOn)
|
||||||
|
{
|
||||||
|
connectionTooltip = new Pair<Rectangle, string>(
|
||||||
|
new Rectangle(iconPos.ToPoint(), new Point((int)iconSize)),
|
||||||
|
TextManager.Get(tooltip)
|
||||||
|
.Replace("[initialdepth]", ((int)(connection.LevelData.InitialDepth * Physics.DisplayToRealWorldRatio)).ToString())
|
||||||
|
.Replace("[submarinecrushdepth]", ((int)(Submarine.MainSub?.RealWorldCrushDepth ?? Level.DefaultRealWorldCrushDepth)).ToString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (GameMain.DebugDraw && zoom > 1.0f && generationParams.ShowLevelTypeNames)
|
if (GameMain.DebugDraw && zoom > 1.0f && generationParams.ShowLevelTypeNames)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -329,8 +329,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
var clones = Clone(selectedList).Where(c => c != null).ToList();
|
var clones = Clone(selectedList).Where(c => c != null).ToList();
|
||||||
selectedList = clones;
|
selectedList = clones;
|
||||||
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(clones, false));
|
|
||||||
selectedList.ForEach(c => c.Move(moveAmount));
|
selectedList.ForEach(c => c.Move(moveAmount));
|
||||||
|
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(clones, false));
|
||||||
}
|
}
|
||||||
else // move
|
else // move
|
||||||
{
|
{
|
||||||
@@ -897,10 +897,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (entities.Count == 0) { return; }
|
if (entities.Count == 0) { return; }
|
||||||
|
|
||||||
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(new List<MapEntity>(entities), true));
|
|
||||||
|
|
||||||
CopyEntities(entities);
|
CopyEntities(entities);
|
||||||
|
|
||||||
|
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(new List<MapEntity>(entities), true));
|
||||||
|
|
||||||
entities.ForEach(e => { if (!e.Removed) { e.Remove(); } });
|
entities.ForEach(e => { if (!e.Removed) { e.Remove(); } });
|
||||||
entities.Clear();
|
entities.Clear();
|
||||||
}
|
}
|
||||||
@@ -913,7 +913,6 @@ namespace Barotrauma
|
|||||||
Clone(copiedList);
|
Clone(copiedList);
|
||||||
|
|
||||||
var clones = mapEntityList.Except(prevEntities).ToList();
|
var clones = mapEntityList.Except(prevEntities).ToList();
|
||||||
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(clones, false));
|
|
||||||
var nonWireClones = clones.Where(c => !(c is Item item) || item.GetComponent<Wire>() == null);
|
var nonWireClones = clones.Where(c => !(c is Item item) || item.GetComponent<Wire>() == null);
|
||||||
if (!nonWireClones.Any()) { nonWireClones = clones; }
|
if (!nonWireClones.Any()) { nonWireClones = clones; }
|
||||||
|
|
||||||
@@ -929,6 +928,8 @@ namespace Barotrauma
|
|||||||
clone.Move(moveAmount);
|
clone.Move(moveAmount);
|
||||||
clone.Submarine = Submarine.MainSub;
|
clone.Submarine = Submarine.MainSub;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(clones, false, handleInventoryBehavior: false));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -238,6 +238,7 @@ namespace Barotrauma
|
|||||||
else if (HiddenInGame) { return; }
|
else if (HiddenInGame) { return; }
|
||||||
|
|
||||||
Color color = IsHighlighted ? GUI.Style.Orange : spriteColor;
|
Color color = IsHighlighted ? GUI.Style.Orange : spriteColor;
|
||||||
|
|
||||||
if (IsSelected && editing)
|
if (IsSelected && editing)
|
||||||
{
|
{
|
||||||
//color = Color.Lerp(color, Color.Gold, 0.5f);
|
//color = Color.Lerp(color, Color.Gold, 0.5f);
|
||||||
@@ -253,6 +254,10 @@ namespace Barotrauma
|
|||||||
thickness: Math.Max(1, (int)(2 / Screen.Selected.Cam.Zoom)));
|
thickness: Math.Max(1, (int)(2 / Screen.Selected.Cam.Zoom)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isWiringMode = editing && SubEditorScreen.IsWiringMode();
|
||||||
|
|
||||||
|
if (isWiringMode) { color *= 0.15f; }
|
||||||
|
|
||||||
Vector2 drawOffset = Submarine == null ? Vector2.Zero : Submarine.DrawPosition;
|
Vector2 drawOffset = Submarine == null ? Vector2.Zero : Submarine.DrawPosition;
|
||||||
|
|
||||||
float depth = GetDrawDepth();
|
float depth = GetDrawDepth();
|
||||||
@@ -261,7 +266,7 @@ namespace Barotrauma
|
|||||||
if (FlippedX) textureOffset.X = -textureOffset.X;
|
if (FlippedX) textureOffset.X = -textureOffset.X;
|
||||||
if (FlippedY) textureOffset.Y = -textureOffset.Y;
|
if (FlippedY) textureOffset.Y = -textureOffset.Y;
|
||||||
|
|
||||||
if (back && damageEffect == null)
|
if (back && damageEffect == null && !isWiringMode)
|
||||||
{
|
{
|
||||||
if (Prefab.BackgroundSprite != null)
|
if (Prefab.BackgroundSprite != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -394,12 +394,10 @@ namespace Barotrauma
|
|||||||
float expandY = MathHelper.Lerp(30.0f, 0.0f, normalizedDistY);
|
float expandY = MathHelper.Lerp(30.0f, 0.0f, normalizedDistY);
|
||||||
|
|
||||||
GUI.DrawLine(spriteBatch,
|
GUI.DrawLine(spriteBatch,
|
||||||
horizontalLine,
|
|
||||||
new Vector2(topLeft.X - expandX, -bottomRight.Y + i * GridSize.Y),
|
new Vector2(topLeft.X - expandX, -bottomRight.Y + i * GridSize.Y),
|
||||||
new Vector2(bottomRight.X + expandX, -bottomRight.Y + i * GridSize.Y),
|
new Vector2(bottomRight.X + expandX, -bottomRight.Y + i * GridSize.Y),
|
||||||
Color.White * (1.0f - normalizedDistY) * alpha, depth: 0.6f, width: 3);
|
Color.White * (1.0f - normalizedDistY) * alpha, depth: 0.6f, width: 3);
|
||||||
GUI.DrawLine(spriteBatch,
|
GUI.DrawLine(spriteBatch,
|
||||||
verticalLine,
|
|
||||||
new Vector2(topLeft.X + i * GridSize.X, -topLeft.Y + expandY),
|
new Vector2(topLeft.X + i * GridSize.X, -topLeft.Y + expandY),
|
||||||
new Vector2(topLeft.X + i * GridSize.X, -bottomRight.Y - expandY),
|
new Vector2(topLeft.X + i * GridSize.X, -bottomRight.Y - expandY),
|
||||||
Color.White * (1.0f - normalizedDistX) * alpha, depth: 0.6f, width: 3);
|
Color.White * (1.0f - normalizedDistX) * alpha, depth: 0.6f, width: 3);
|
||||||
|
|||||||
@@ -10,10 +10,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (GameMain.Client == null) { return; }
|
if (GameMain.Client == null) { return; }
|
||||||
|
|
||||||
Vector2 newVelocity = Body.LinearVelocity;
|
Body.CorrectPosition(positionBuffer, out Vector2 newPosition, out Vector2 newVelocity, out _, out _);
|
||||||
Vector2 newPosition = Body.SimPosition;
|
|
||||||
|
|
||||||
Body.CorrectPosition(positionBuffer, out newPosition, out newVelocity, out _, out _);
|
|
||||||
Vector2 moveAmount = ConvertUnits.ToDisplayUnits(newPosition - Body.SimPosition);
|
Vector2 moveAmount = ConvertUnits.ToDisplayUnits(newPosition - Body.SimPosition);
|
||||||
newVelocity = newVelocity.ClampLength(100.0f);
|
newVelocity = newVelocity.ClampLength(100.0f);
|
||||||
if (!MathUtils.IsValid(newVelocity) || moveAmount.LengthSquared() < 0.0001f)
|
if (!MathUtils.IsValid(newVelocity) || moveAmount.LengthSquared() < 0.0001f)
|
||||||
@@ -24,12 +21,12 @@ namespace Barotrauma
|
|||||||
List<Submarine> subsToMove = submarine.GetConnectedSubs();
|
List<Submarine> subsToMove = submarine.GetConnectedSubs();
|
||||||
foreach (Submarine dockedSub in subsToMove)
|
foreach (Submarine dockedSub in subsToMove)
|
||||||
{
|
{
|
||||||
if (dockedSub == submarine) continue;
|
if (dockedSub == submarine) { continue; }
|
||||||
//clear the position buffer of the docked subs to prevent unnecessary position corrections
|
//clear the position buffer of the docked subs to prevent unnecessary position corrections
|
||||||
dockedSub.SubBody.positionBuffer.Clear();
|
dockedSub.SubBody.positionBuffer.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
Submarine closestSub = null;
|
Submarine closestSub;
|
||||||
if (Character.Controlled == null)
|
if (Character.Controlled == null)
|
||||||
{
|
{
|
||||||
closestSub = Submarine.FindClosest(GameMain.GameScreen.Cam.Position);
|
closestSub = Submarine.FindClosest(GameMain.GameScreen.Cam.Position);
|
||||||
@@ -63,5 +60,33 @@ namespace Barotrauma
|
|||||||
if (Character.Controlled != null) Character.Controlled.CursorPosition += moveAmount;
|
if (Character.Controlled != null) Character.Controlled.CursorPosition += moveAmount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void PlayDamageSounds(Dictionary<Structure, float> damagedStructures, Vector2 impactSimPos, float impact, string soundTag)
|
||||||
|
{
|
||||||
|
if (impact < MinCollisionImpact) { return; }
|
||||||
|
|
||||||
|
//play a damage sound for the structure that took the most damage
|
||||||
|
float maxDamage = 0.0f;
|
||||||
|
Structure maxDamageStructure = null;
|
||||||
|
foreach (KeyValuePair<Structure, float> structureDamage in damagedStructures)
|
||||||
|
{
|
||||||
|
if (maxDamageStructure == null || structureDamage.Value > maxDamage)
|
||||||
|
{
|
||||||
|
maxDamage = structureDamage.Value;
|
||||||
|
maxDamageStructure = structureDamage.Key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxDamageStructure != null)
|
||||||
|
{
|
||||||
|
SoundPlayer.PlayDamageSound(
|
||||||
|
soundTag,
|
||||||
|
impact * 10.0f,
|
||||||
|
ConvertUnits.ToDisplayUnits(impactSimPos),
|
||||||
|
MathHelper.Lerp(2000.0f, 10000.0f, (impact - MinCollisionImpact) / 2.0f),
|
||||||
|
maxDamageStructure.Tags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ namespace Barotrauma.Networking
|
|||||||
Entity targetEntity = Entity.FindEntityByID(msg.ReadUInt16());
|
Entity targetEntity = Entity.FindEntityByID(msg.ReadUInt16());
|
||||||
int optionIndex = msg.ReadByte();
|
int optionIndex = msg.ReadByte();
|
||||||
OrderTarget orderTargetPosition = null;
|
OrderTarget orderTargetPosition = null;
|
||||||
|
Order.OrderTargetType orderTargetType = (Order.OrderTargetType)msg.ReadByte();
|
||||||
|
int wallSectionIndex = 0;
|
||||||
if (msg.ReadBoolean())
|
if (msg.ReadBoolean())
|
||||||
{
|
{
|
||||||
var x = msg.ReadSingle();
|
var x = msg.ReadSingle();
|
||||||
@@ -57,6 +59,10 @@ namespace Barotrauma.Networking
|
|||||||
var hull = Entity.FindEntityByID(msg.ReadUInt16()) as Hull;
|
var hull = Entity.FindEntityByID(msg.ReadUInt16()) as Hull;
|
||||||
orderTargetPosition = new OrderTarget(new Vector2(x, y), hull, creatingFromExistingData: true);
|
orderTargetPosition = new OrderTarget(new Vector2(x, y), hull, creatingFromExistingData: true);
|
||||||
}
|
}
|
||||||
|
else if(orderTargetType == Order.OrderTargetType.WallSection)
|
||||||
|
{
|
||||||
|
wallSectionIndex = msg.ReadByte();
|
||||||
|
}
|
||||||
|
|
||||||
Order orderPrefab;
|
Order orderPrefab;
|
||||||
if (orderIndex < 0 || orderIndex >= Order.PrefabList.Count)
|
if (orderIndex < 0 || orderIndex >= Order.PrefabList.Count)
|
||||||
@@ -78,17 +84,31 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
if (GameMain.Client.GameStarted && Screen.Selected == GameMain.GameScreen)
|
if (GameMain.Client.GameStarted && Screen.Selected == GameMain.GameScreen)
|
||||||
{
|
{
|
||||||
var order = orderTargetPosition == null ?
|
Order order = null;
|
||||||
new Order(orderPrefab, targetEntity, orderPrefab.GetTargetItemComponent(targetEntity as Item), orderGiver: senderCharacter) :
|
switch (orderTargetType)
|
||||||
new Order(orderPrefab, orderTargetPosition, orderGiver: senderCharacter);
|
|
||||||
|
|
||||||
if (order.TargetAllCharacters)
|
|
||||||
{
|
{
|
||||||
GameMain.GameSession?.CrewManager?.AddOrder(order, orderPrefab.FadeOutTime);
|
case Order.OrderTargetType.Entity:
|
||||||
|
order = new Order(orderPrefab, targetEntity, orderPrefab.GetTargetItemComponent(targetEntity as Item), orderGiver: senderCharacter);
|
||||||
|
break;
|
||||||
|
case Order.OrderTargetType.Position:
|
||||||
|
order = new Order(orderPrefab, orderTargetPosition, orderGiver: senderCharacter);
|
||||||
|
break;
|
||||||
|
case Order.OrderTargetType.WallSection:
|
||||||
|
order = new Order(orderPrefab, targetEntity as Structure, wallSectionIndex, orderGiver: senderCharacter);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if (targetCharacter != null)
|
|
||||||
|
if (order != null)
|
||||||
{
|
{
|
||||||
targetCharacter.SetOrder(order, orderOption, senderCharacter);
|
if (order.TargetAllCharacters)
|
||||||
|
{
|
||||||
|
var fadeOutTime = !orderPrefab.IsIgnoreOrder ? (float?)orderPrefab.FadeOutTime : null;
|
||||||
|
GameMain.GameSession?.CrewManager?.AddOrder(order, fadeOutTime);
|
||||||
|
}
|
||||||
|
else if (targetCharacter != null)
|
||||||
|
{
|
||||||
|
targetCharacter.SetOrder(order, orderOption, senderCharacter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
using System;
|
using System.Diagnostics;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using Barotrauma.IO;
|
|
||||||
using System.IO.Pipes;
|
using System.IO.Pipes;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Barotrauma.Networking
|
namespace Barotrauma.Networking
|
||||||
{
|
{
|
||||||
@@ -26,7 +20,15 @@ namespace Barotrauma.Networking
|
|||||||
PrivateStart();
|
PrivateStart();
|
||||||
|
|
||||||
processInfo.Arguments += " -pipes " + writePipe.GetClientHandleAsString() + " " + readPipe.GetClientHandleAsString();
|
processInfo.Arguments += " -pipes " + writePipe.GetClientHandleAsString() + " " + readPipe.GetClientHandleAsString();
|
||||||
Process = Process.Start(processInfo);
|
try
|
||||||
|
{
|
||||||
|
Process = Process.Start(processInfo);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError($"Failed to start ChildServerRelay Process. File: {processInfo.FileName}, arguments: {processInfo.Arguments}");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
localHandlesDisposed = false;
|
localHandlesDisposed = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -903,6 +903,9 @@ namespace Barotrauma.Networking
|
|||||||
case ServerPacketHeader.CREW:
|
case ServerPacketHeader.CREW:
|
||||||
campaign?.ClientReadCrew(inc);
|
campaign?.ClientReadCrew(inc);
|
||||||
break;
|
break;
|
||||||
|
case ServerPacketHeader.READY_CHECK:
|
||||||
|
ReadyCheck.ClientRead(inc);
|
||||||
|
break;
|
||||||
case ServerPacketHeader.FILE_TRANSFER:
|
case ServerPacketHeader.FILE_TRANSFER:
|
||||||
fileReceiver.ReadMessage(inc);
|
fileReceiver.ReadMessage(inc);
|
||||||
break;
|
break;
|
||||||
@@ -976,7 +979,7 @@ namespace Barotrauma.Networking
|
|||||||
string errorMsg = "Level equality check failed. The level generated at your end doesn't match the level generated by the server" +
|
string errorMsg = "Level equality check failed. The level generated at your end doesn't match the level generated by the server" +
|
||||||
" (client value #" + i + ": " + Level.Loaded.EqualityCheckValues[i] +
|
" (client value #" + i + ": " + Level.Loaded.EqualityCheckValues[i] +
|
||||||
", server value #" + i + ": " + levelEqualityCheckValues[i].ToString("X") +
|
", server value #" + i + ": " + levelEqualityCheckValues[i].ToString("X") +
|
||||||
", level value count: " + levelEqualityCheckValues.Count.ToString("X") +
|
", level value count: " + levelEqualityCheckValues.Count +
|
||||||
", seed: " + Level.Loaded.Seed +
|
", seed: " + Level.Loaded.Seed +
|
||||||
", sub: " + Submarine.MainSub.Info.Name + " (" + Submarine.MainSub.Info.MD5Hash.ShortHash + ")" +
|
", sub: " + Submarine.MainSub.Info.Name + " (" + Submarine.MainSub.Info.MD5Hash.ShortHash + ")" +
|
||||||
", mirrored: " + Level.Loaded.Mirrored + ").";
|
", mirrored: " + Level.Loaded.Mirrored + ").";
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ namespace Barotrauma
|
|||||||
CreateLabeledNumberInput(parent, 0, 20, nameof(AllowedWireDisconnectionsPerMinute));
|
CreateLabeledNumberInput(parent, 0, 20, nameof(AllowedWireDisconnectionsPerMinute));
|
||||||
CreateLabeledSlider(parent, 0.0f, 20.0f, 0.5f, nameof(WireDisconnectionKarmaDecrease));
|
CreateLabeledSlider(parent, 0.0f, 20.0f, 0.5f, nameof(WireDisconnectionKarmaDecrease));
|
||||||
CreateLabeledSlider(parent, 0.0f, 30.0f, 1.0f, nameof(SpamFilterKarmaDecrease));
|
CreateLabeledSlider(parent, 0.0f, 30.0f, 1.0f, nameof(SpamFilterKarmaDecrease));
|
||||||
|
CreateLabeledSlider(parent, 0.0f, 1.0f, 0.01f, nameof(BallastFloraKarmaIncrease));
|
||||||
|
|
||||||
//hide these for now if a localized text is not available
|
//hide these for now if a localized text is not available
|
||||||
if (TextManager.ContainsTag("Karma." + nameof(DangerousItemStealKarmaDecrease)))
|
if (TextManager.ContainsTag("Karma." + nameof(DangerousItemStealKarmaDecrease)))
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ namespace Barotrauma.Networking
|
|||||||
msg.Write(TargetCharacter == null ? (UInt16)0 : TargetCharacter.ID);
|
msg.Write(TargetCharacter == null ? (UInt16)0 : TargetCharacter.ID);
|
||||||
msg.Write(TargetEntity is Entity ? (TargetEntity as Entity).ID : (UInt16)0);
|
msg.Write(TargetEntity is Entity ? (TargetEntity as Entity).ID : (UInt16)0);
|
||||||
msg.Write((byte)Array.IndexOf(Order.Prefab.Options, OrderOption));
|
msg.Write((byte)Array.IndexOf(Order.Prefab.Options, OrderOption));
|
||||||
if (TargetEntity is OrderTarget orderTarget)
|
msg.Write((byte)Order.TargetType);
|
||||||
|
if (Order.TargetType == Order.OrderTargetType.Position && TargetEntity is OrderTarget orderTarget)
|
||||||
{
|
{
|
||||||
msg.Write(true);
|
msg.Write(true);
|
||||||
msg.Write(orderTarget.Position.X);
|
msg.Write(orderTarget.Position.X);
|
||||||
@@ -23,6 +24,10 @@ namespace Barotrauma.Networking
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
msg.Write(false);
|
msg.Write(false);
|
||||||
|
if (Order.TargetType == Order.OrderTargetType.WallSection)
|
||||||
|
{
|
||||||
|
msg.Write((byte)(WallSectionIndex ?? Order.WallSectionIndex ?? 0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,131 +0,0 @@
|
|||||||
using Microsoft.Xna.Framework;
|
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Barotrauma.Particles
|
|
||||||
{
|
|
||||||
class Decal
|
|
||||||
{
|
|
||||||
public readonly DecalPrefab Prefab;
|
|
||||||
private Vector2 position;
|
|
||||||
|
|
||||||
public readonly Sprite Sprite;
|
|
||||||
|
|
||||||
private float fadeTimer;
|
|
||||||
|
|
||||||
public float FadeTimer
|
|
||||||
{
|
|
||||||
get { return fadeTimer; }
|
|
||||||
set { fadeTimer = MathHelper.Clamp(value, 0.0f, LifeTime); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public float FadeInTime
|
|
||||||
{
|
|
||||||
get { return Prefab.FadeInTime; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public float FadeOutTime
|
|
||||||
{
|
|
||||||
get { return Prefab.FadeOutTime; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public float LifeTime
|
|
||||||
{
|
|
||||||
get { return Prefab.LifeTime; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Color Color
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector2 WorldPosition
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
Vector2 worldPos = position
|
|
||||||
+ clippedSourceRect.Size.ToVector2() / 2 * scale
|
|
||||||
+ hull.Rect.Location.ToVector2();
|
|
||||||
if (hull.Submarine != null) { worldPos += hull.Submarine.DrawPosition; }
|
|
||||||
return worldPos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Hull hull;
|
|
||||||
|
|
||||||
private float scale;
|
|
||||||
|
|
||||||
private Rectangle clippedSourceRect;
|
|
||||||
|
|
||||||
public Decal(DecalPrefab prefab, float scale, Vector2 worldPosition, Hull hull)
|
|
||||||
{
|
|
||||||
Prefab = prefab;
|
|
||||||
|
|
||||||
this.hull = hull;
|
|
||||||
|
|
||||||
//transform to hull-relative coordinates so we don't have to worry about the hull moving
|
|
||||||
position = worldPosition - hull.WorldRect.Location.ToVector2();
|
|
||||||
|
|
||||||
Vector2 drawPos = position + hull.Rect.Location.ToVector2();
|
|
||||||
|
|
||||||
Sprite = prefab.Sprites[Rand.Range(0, prefab.Sprites.Count, Rand.RandSync.Unsynced)];
|
|
||||||
Color = prefab.Color;
|
|
||||||
|
|
||||||
Rectangle drawRect = new Rectangle(
|
|
||||||
(int)(drawPos.X - Sprite.size.X / 2 * scale),
|
|
||||||
(int)(drawPos.Y + Sprite.size.Y / 2 * scale),
|
|
||||||
(int)(Sprite.size.X * scale),
|
|
||||||
(int)(Sprite.size.Y * scale));
|
|
||||||
|
|
||||||
Rectangle overFlowAmount = new Rectangle(
|
|
||||||
(int)Math.Max(hull.Rect.X - drawRect.X, 0.0f),
|
|
||||||
(int)Math.Max(drawRect.Y - hull.Rect.Y, 0.0f),
|
|
||||||
(int)Math.Max(drawRect.Right - hull.Rect.Right, 0.0f),
|
|
||||||
(int)Math.Max((hull.Rect.Y - hull.Rect.Height) - (drawRect.Y - drawRect.Height), 0.0f));
|
|
||||||
|
|
||||||
clippedSourceRect = new Rectangle(
|
|
||||||
Sprite.SourceRect.X + (int)(overFlowAmount.X / scale),
|
|
||||||
Sprite.SourceRect.Y + (int)(overFlowAmount.Y / scale),
|
|
||||||
Sprite.SourceRect.Width - (int)((overFlowAmount.X + overFlowAmount.Width) / scale),
|
|
||||||
Sprite.SourceRect.Height - (int)((overFlowAmount.Y + overFlowAmount.Height) / scale));
|
|
||||||
|
|
||||||
position -= new Vector2(Sprite.size.X / 2 * scale - overFlowAmount.X, -Sprite.size.Y / 2 * scale + overFlowAmount.Y);
|
|
||||||
|
|
||||||
this.scale = scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Update(float deltaTime)
|
|
||||||
{
|
|
||||||
fadeTimer += deltaTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void StopFadeIn()
|
|
||||||
{
|
|
||||||
Color *= GetAlpha();
|
|
||||||
fadeTimer = Prefab.FadeInTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Draw(SpriteBatch spriteBatch, Hull hull, float depth)
|
|
||||||
{
|
|
||||||
Vector2 drawPos = position + hull.Rect.Location.ToVector2();
|
|
||||||
if (hull.Submarine != null) { drawPos += hull.Submarine.DrawPosition; }
|
|
||||||
drawPos.Y = -drawPos.Y;
|
|
||||||
|
|
||||||
spriteBatch.Draw(Sprite.Texture, drawPos, clippedSourceRect, Color * GetAlpha(), 0, Vector2.Zero, scale, SpriteEffects.None, depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
private float GetAlpha()
|
|
||||||
{
|
|
||||||
if (fadeTimer < Prefab.FadeInTime)
|
|
||||||
{
|
|
||||||
return fadeTimer / Prefab.FadeInTime;
|
|
||||||
}
|
|
||||||
else if (fadeTimer > Prefab.LifeTime - Prefab.FadeOutTime)
|
|
||||||
{
|
|
||||||
return (Prefab.LifeTime - fadeTimer) / Prefab.FadeOutTime;
|
|
||||||
}
|
|
||||||
return 1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
using Microsoft.Xna.Framework;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Xml.Linq;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Barotrauma.Particles
|
|
||||||
{
|
|
||||||
class DecalManager
|
|
||||||
{
|
|
||||||
public PrefabCollection<DecalPrefab> Prefabs { get; private set; }
|
|
||||||
|
|
||||||
public DecalManager()
|
|
||||||
{
|
|
||||||
Prefabs = new PrefabCollection<DecalPrefab>();
|
|
||||||
foreach (ContentFile configFile in GameMain.Instance.GetFilesOfType(ContentType.Decals))
|
|
||||||
{
|
|
||||||
LoadFromFile(configFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LoadFromFile(ContentFile configFile)
|
|
||||||
{
|
|
||||||
XDocument doc = XMLExtensions.TryLoadXml(configFile.Path);
|
|
||||||
if (doc == null) { return; }
|
|
||||||
|
|
||||||
bool allowOverriding = false;
|
|
||||||
var mainElement = doc.Root;
|
|
||||||
if (doc.Root.IsOverride())
|
|
||||||
{
|
|
||||||
mainElement = doc.Root.FirstElement();
|
|
||||||
allowOverriding = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (XElement sourceElement in mainElement.Elements())
|
|
||||||
{
|
|
||||||
var element = sourceElement.IsOverride() ? sourceElement.FirstElement() : sourceElement;
|
|
||||||
string name = element.Name.ToString().ToLowerInvariant();
|
|
||||||
if (Prefabs.ContainsKey(name))
|
|
||||||
{
|
|
||||||
if (allowOverriding || sourceElement.IsOverride())
|
|
||||||
{
|
|
||||||
DebugConsole.NewMessage($"Overriding the existing decal prefab '{name}' using the file '{configFile.Path}'", Color.Yellow);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DebugConsole.ThrowError($"Error in '{configFile.Path}': Duplicate decal prefab '{name}' found in '{configFile.Path}'! Each decal prefab must have a unique name. " +
|
|
||||||
"Use <override></override> tags to override prefabs.");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Prefabs.Add(new DecalPrefab(element, configFile), allowOverriding || sourceElement.IsOverride());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RemoveByFile(string filePath)
|
|
||||||
{
|
|
||||||
Prefabs.RemoveByFile(filePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Decal CreateDecal(string decalName, float scale, Vector2 worldPosition, Hull hull)
|
|
||||||
{
|
|
||||||
if (!Prefabs.ContainsKey(decalName.ToLowerInvariant()))
|
|
||||||
{
|
|
||||||
DebugConsole.ThrowError("Decal prefab " + decalName + " not found!");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
DecalPrefab prefab = Prefabs[decalName];
|
|
||||||
|
|
||||||
return new Decal(prefab, scale, worldPosition, hull);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
using Microsoft.Xna.Framework;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Xml.Linq;
|
|
||||||
|
|
||||||
namespace Barotrauma.Particles
|
|
||||||
{
|
|
||||||
class DecalPrefab : IPrefab, IDisposable
|
|
||||||
{
|
|
||||||
public readonly string Name;
|
|
||||||
|
|
||||||
public string OriginalName { get { return Name; } }
|
|
||||||
|
|
||||||
private string _identifier;
|
|
||||||
public string Identifier
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_identifier == null)
|
|
||||||
{
|
|
||||||
_identifier = Name.ToLowerInvariant();
|
|
||||||
}
|
|
||||||
return _identifier;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string FilePath { get; private set; }
|
|
||||||
|
|
||||||
public ContentPackage ContentPackage { get; private set; }
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
foreach (Sprite spr in Sprites)
|
|
||||||
{
|
|
||||||
spr.Remove();
|
|
||||||
}
|
|
||||||
Sprites.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public readonly List<Sprite> Sprites;
|
|
||||||
|
|
||||||
public readonly Color Color;
|
|
||||||
|
|
||||||
public readonly float LifeTime;
|
|
||||||
public readonly float FadeOutTime;
|
|
||||||
public readonly float FadeInTime;
|
|
||||||
|
|
||||||
public DecalPrefab(XElement element, ContentFile file)
|
|
||||||
{
|
|
||||||
Name = element.Name.ToString();
|
|
||||||
|
|
||||||
FilePath = file.Path;
|
|
||||||
|
|
||||||
ContentPackage = file.ContentPackage;
|
|
||||||
|
|
||||||
Sprites = new List<Sprite>();
|
|
||||||
|
|
||||||
foreach (XElement subElement in element.Elements())
|
|
||||||
{
|
|
||||||
if (subElement.Name.ToString().Equals("sprite", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Sprites.Add(new Sprite(subElement));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Color = new Color(element.GetAttributeVector4("color", Vector4.One));
|
|
||||||
|
|
||||||
LifeTime = element.GetAttributeFloat("lifetime", 10.0f);
|
|
||||||
FadeOutTime = Math.Min(LifeTime, element.GetAttributeFloat("fadeouttime", 1.0f));
|
|
||||||
FadeInTime = Math.Min(LifeTime - FadeOutTime, element.GetAttributeFloat("fadeintime", 0.0f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -483,7 +483,7 @@ namespace Barotrauma.Particles
|
|||||||
|
|
||||||
if (prefab.GrowTime > 0.0f && totalLifeTime - lifeTime < prefab.GrowTime)
|
if (prefab.GrowTime > 0.0f && totalLifeTime - lifeTime < prefab.GrowTime)
|
||||||
{
|
{
|
||||||
drawSize *= ((totalLifeTime - lifeTime) / prefab.GrowTime);
|
drawSize *= MathUtils.SmoothStep((totalLifeTime - lifeTime) / prefab.GrowTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color currColor = new Color(color.ToVector4() * ColorMultiplier);
|
Color currColor = new Color(color.ToVector4() * ColorMultiplier);
|
||||||
|
|||||||
+11
-10
@@ -372,6 +372,9 @@ namespace Barotrauma.CharacterEditor
|
|||||||
{
|
{
|
||||||
base.Update(deltaTime);
|
base.Update(deltaTime);
|
||||||
if (Wizard.instance != null) { return; }
|
if (Wizard.instance != null) { return; }
|
||||||
|
|
||||||
|
GameMain.LightManager?.Update((float)deltaTime);
|
||||||
|
|
||||||
spriteSheetRect = CalculateSpritesheetRectangle();
|
spriteSheetRect = CalculateSpritesheetRectangle();
|
||||||
// Handle shortcut keys
|
// Handle shortcut keys
|
||||||
if (PlayerInput.KeyHit(Keys.F1))
|
if (PlayerInput.KeyHit(Keys.F1))
|
||||||
@@ -787,7 +790,7 @@ namespace Barotrauma.CharacterEditor
|
|||||||
if (GameMain.LightManager.LightingEnabled)
|
if (GameMain.LightManager.LightingEnabled)
|
||||||
{
|
{
|
||||||
GameMain.LightManager.ObstructVision = Character.Controlled.ObstructVision;
|
GameMain.LightManager.ObstructVision = Character.Controlled.ObstructVision;
|
||||||
GameMain.LightManager.UpdateLightMap(graphics, spriteBatch, cam);
|
GameMain.LightManager.RenderLightMap(graphics, spriteBatch, cam);
|
||||||
GameMain.LightManager.UpdateObstructVision(graphics, spriteBatch, cam, Character.Controlled.CursorWorldPosition);
|
GameMain.LightManager.UpdateObstructVision(graphics, spriteBatch, cam, Character.Controlled.CursorWorldPosition);
|
||||||
}
|
}
|
||||||
base.Draw(deltaTime, graphics, spriteBatch);
|
base.Draw(deltaTime, graphics, spriteBatch);
|
||||||
@@ -2786,9 +2789,7 @@ namespace Barotrauma.CharacterEditor
|
|||||||
};
|
};
|
||||||
// Spacing
|
// Spacing
|
||||||
new GUIFrame(new RectTransform(buttonSize / 2, layoutGroup.RectTransform), style: null) { CanBeFocused = false };
|
new GUIFrame(new RectTransform(buttonSize / 2, layoutGroup.RectTransform), style: null) { CanBeFocused = false };
|
||||||
Vector2 messageBoxRelSize = new Vector2(0.5f, 0.5f);
|
Vector2 messageBoxRelSize = new Vector2(0.5f, 0.7f);
|
||||||
int messageBoxWidth = GameMain.GraphicsWidth / 2;
|
|
||||||
int messageBoxHeight = GameMain.GraphicsHeight / 2;
|
|
||||||
var saveRagdollButton = new GUIButton(new RectTransform(buttonSize, layoutGroup.RectTransform), GetCharacterEditorTranslation("SaveRagdoll"));
|
var saveRagdollButton = new GUIButton(new RectTransform(buttonSize, layoutGroup.RectTransform), GetCharacterEditorTranslation("SaveRagdoll"));
|
||||||
saveRagdollButton.OnClicked += (button, userData) =>
|
saveRagdollButton.OnClicked += (button, userData) =>
|
||||||
{
|
{
|
||||||
@@ -2908,12 +2909,12 @@ namespace Barotrauma.CharacterEditor
|
|||||||
{
|
{
|
||||||
var box = new GUIMessageBox(GetCharacterEditorTranslation("SaveAnimation"), string.Empty, new string[] { TextManager.Get("Cancel"), TextManager.Get("Save") }, messageBoxRelSize);
|
var box = new GUIMessageBox(GetCharacterEditorTranslation("SaveAnimation"), string.Empty, new string[] { TextManager.Get("Cancel"), TextManager.Get("Save") }, messageBoxRelSize);
|
||||||
var textArea = new GUIFrame(new RectTransform(new Vector2(1, 0.1f), box.Content.RectTransform) { MinSize = new Point(350, 30) }, style: null);
|
var textArea = new GUIFrame(new RectTransform(new Vector2(1, 0.1f), box.Content.RectTransform) { MinSize = new Point(350, 30) }, style: null);
|
||||||
var inputLabel = new GUITextBlock(new RectTransform(new Vector2(0.3f, 1), textArea.RectTransform) { MinSize = new Point(250, 30) }, $"{GetCharacterEditorTranslation("ProvideFileName")}: ");
|
var inputLabel = new GUITextBlock(new RectTransform(new Vector2(0.3f, 1), textArea.RectTransform, Anchor.CenterLeft) { MinSize = new Point(250, 30) }, $"{GetCharacterEditorTranslation("ProvideFileName")}: ");
|
||||||
var inputField = new GUITextBox(new RectTransform(new Vector2(0.5f, 1), textArea.RectTransform, Anchor.TopRight) { MinSize = new Point(100, 30) }, CurrentAnimation.Name);
|
var inputField = new GUITextBox(new RectTransform(new Vector2(0.45f, 1), textArea.RectTransform, Anchor.CenterRight) { MinSize = new Point(100, 30) }, CurrentAnimation.Name);
|
||||||
// Type filtering
|
// Type filtering
|
||||||
var typeSelectionArea = new GUIFrame(new RectTransform(new Vector2(1f, 0.1f), box.Content.RectTransform) { MinSize = new Point(0, 30) }, style: null);
|
var typeSelectionArea = new GUIFrame(new RectTransform(new Vector2(1f, 0.1f), box.Content.RectTransform) { MinSize = new Point(0, 30) }, style: null);
|
||||||
var typeLabel = new GUITextBlock(new RectTransform(new Vector2(0.4f, 1), typeSelectionArea.RectTransform, Anchor.TopCenter, Pivot.TopRight), $"{GetCharacterEditorTranslation("SelectAnimationType")}: ");
|
var typeLabel = new GUITextBlock(new RectTransform(new Vector2(0.45f, 1), typeSelectionArea.RectTransform, Anchor.CenterLeft), $"{GetCharacterEditorTranslation("SelectAnimationType")}: ");
|
||||||
var typeDropdown = new GUIDropDown(new RectTransform(new Vector2(0.4f, 1), typeSelectionArea.RectTransform, Anchor.TopCenter, Pivot.TopLeft), elementCount: 4);
|
var typeDropdown = new GUIDropDown(new RectTransform(new Vector2(0.45f, 1), typeSelectionArea.RectTransform, Anchor.CenterRight), elementCount: 4);
|
||||||
foreach (object enumValue in Enum.GetValues(typeof(AnimationType)))
|
foreach (object enumValue in Enum.GetValues(typeof(AnimationType)))
|
||||||
{
|
{
|
||||||
if (!(enumValue is AnimationType.NotDefined))
|
if (!(enumValue is AnimationType.NotDefined))
|
||||||
@@ -2964,8 +2965,8 @@ namespace Barotrauma.CharacterEditor
|
|||||||
deleteButton.Enabled = false;
|
deleteButton.Enabled = false;
|
||||||
// Type filtering
|
// Type filtering
|
||||||
var typeSelectionArea = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.1f), loadBox.Content.RectTransform) { MinSize = new Point(0, 30) }, style: null);
|
var typeSelectionArea = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.1f), loadBox.Content.RectTransform) { MinSize = new Point(0, 30) }, style: null);
|
||||||
var typeLabel = new GUITextBlock(new RectTransform(new Vector2(0.4f, 1), typeSelectionArea.RectTransform, Anchor.TopCenter, Pivot.TopRight), $"{GetCharacterEditorTranslation("SelectAnimationType")}: ");
|
var typeLabel = new GUITextBlock(new RectTransform(new Vector2(0.45f, 1), typeSelectionArea.RectTransform, Anchor.CenterLeft), $"{GetCharacterEditorTranslation("SelectAnimationType")}: ");
|
||||||
var typeDropdown = new GUIDropDown(new RectTransform(new Vector2(0.4f, 1), typeSelectionArea.RectTransform, Anchor.TopCenter, Pivot.TopLeft), elementCount: 4);
|
var typeDropdown = new GUIDropDown(new RectTransform(new Vector2(0.45f, 1), typeSelectionArea.RectTransform, Anchor.CenterRight), elementCount: 4);
|
||||||
foreach (object enumValue in Enum.GetValues(typeof(AnimationType)))
|
foreach (object enumValue in Enum.GetValues(typeof(AnimationType)))
|
||||||
{
|
{
|
||||||
if (!(enumValue is AnimationType.NotDefined))
|
if (!(enumValue is AnimationType.NotDefined))
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ namespace Barotrauma
|
|||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
|
|
||||||
graphics.SetRenderTarget(null);
|
graphics.SetRenderTarget(null);
|
||||||
GameMain.LightManager.UpdateLightMap(graphics, spriteBatch, cam, renderTarget);
|
GameMain.LightManager.RenderLightMap(graphics, spriteBatch, cam, renderTarget);
|
||||||
|
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
graphics.SetRenderTarget(renderTargetBackground);
|
graphics.SetRenderTarget(renderTargetBackground);
|
||||||
|
|||||||
@@ -24,24 +24,26 @@ namespace Barotrauma
|
|||||||
get { return cam; }
|
get { return cam; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private GUIFrame leftPanel, rightPanel, bottomPanel, topPanel;
|
private readonly GUIFrame leftPanel, rightPanel, bottomPanel, topPanel;
|
||||||
|
|
||||||
private LevelGenerationParams selectedParams;
|
private LevelGenerationParams selectedParams;
|
||||||
private LevelObjectPrefab selectedLevelObject;
|
private LevelObjectPrefab selectedLevelObject;
|
||||||
|
|
||||||
private GUIListBox paramsList, ruinParamsList, outpostParamsList, levelObjectList;
|
private readonly GUIListBox paramsList, ruinParamsList, caveParamsList, outpostParamsList, levelObjectList;
|
||||||
private GUIListBox editorContainer;
|
private readonly GUIListBox editorContainer;
|
||||||
|
|
||||||
private GUIButton spriteEditDoneButton;
|
private readonly GUIButton spriteEditDoneButton;
|
||||||
|
|
||||||
private GUITextBox seedBox;
|
private readonly GUITextBox seedBox;
|
||||||
|
|
||||||
private GUITickBox lightingEnabled, cursorLightEnabled;
|
private readonly GUITickBox lightingEnabled, cursorLightEnabled;
|
||||||
|
|
||||||
private Sprite editingSprite;
|
private Sprite editingSprite;
|
||||||
|
|
||||||
private LightSource pointerLightSource;
|
private LightSource pointerLightSource;
|
||||||
|
|
||||||
|
private readonly Color[] tunnelDebugColors = new Color[] { Color.White, Color.Cyan, Color.LightGreen, Color.Red, Color.LightYellow, Color.LightSeaGreen };
|
||||||
|
|
||||||
public LevelEditorScreen()
|
public LevelEditorScreen()
|
||||||
{
|
{
|
||||||
cam = new Camera()
|
cam = new Camera()
|
||||||
@@ -78,8 +80,17 @@ namespace Barotrauma
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var caveTitle = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedLeftPanel.RectTransform), TextManager.Get("leveleditor.caveparams"), font: GUI.SubHeadingFont);
|
||||||
|
|
||||||
|
caveParamsList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.1f), paddedLeftPanel.RectTransform));
|
||||||
|
caveParamsList.OnSelected += (GUIComponent component, object obj) =>
|
||||||
|
{
|
||||||
|
CreateCaveParamsEditor(obj as CaveGenerationParams);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
var outpostTitle = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedLeftPanel.RectTransform), TextManager.Get("leveleditor.outpostparams"), font: GUI.SubHeadingFont);
|
var outpostTitle = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedLeftPanel.RectTransform), TextManager.Get("leveleditor.outpostparams"), font: GUI.SubHeadingFont);
|
||||||
GUITextBlock.AutoScaleAndNormalize(ruinTitle, outpostTitle);
|
GUITextBlock.AutoScaleAndNormalize(ruinTitle, caveTitle, outpostTitle);
|
||||||
|
|
||||||
outpostParamsList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.2f), paddedLeftPanel.RectTransform));
|
outpostParamsList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.2f), paddedLeftPanel.RectTransform));
|
||||||
outpostParamsList.OnSelected += (GUIComponent component, object obj) =>
|
outpostParamsList.OnSelected += (GUIComponent component, object obj) =>
|
||||||
@@ -237,13 +248,17 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
OnClicked = (btn, obj) =>
|
OnClicked = (btn, obj) =>
|
||||||
{
|
{
|
||||||
|
bool wasLevelLoaded = Level.Loaded != null;
|
||||||
Submarine.Unload();
|
Submarine.Unload();
|
||||||
GameMain.LightManager.ClearLights();
|
GameMain.LightManager.ClearLights();
|
||||||
LevelData levelData = LevelData.CreateRandom(seedBox.Text, generationParams: selectedParams);
|
LevelData levelData = LevelData.CreateRandom(seedBox.Text, generationParams: selectedParams);
|
||||||
levelData.ForceOutpostGenerationParams = outpostParamsList.SelectedData as OutpostGenerationParams;
|
levelData.ForceOutpostGenerationParams = outpostParamsList.SelectedData as OutpostGenerationParams;
|
||||||
Level.Generate(levelData, mirror: false);
|
Level.Generate(levelData, mirror: false);
|
||||||
GameMain.LightManager.AddLight(pointerLightSource);
|
GameMain.LightManager.AddLight(pointerLightSource);
|
||||||
cam.Position = new Vector2(Level.Loaded.Size.X / 2, Level.Loaded.Size.Y / 2);
|
if (!wasLevelLoaded || cam.Position.X < 0 || cam.Position.Y < 0 || cam.Position.Y > Level.Loaded.Size.X || cam.Position.Y > Level.Loaded.Size.Y)
|
||||||
|
{
|
||||||
|
cam.Position = new Vector2(Level.Loaded.Size.X / 2, Level.Loaded.Size.Y / 2);
|
||||||
|
}
|
||||||
foreach (GUITextBlock param in paramsList.Content.Children)
|
foreach (GUITextBlock param in paramsList.Content.Children)
|
||||||
{
|
{
|
||||||
param.TextColor = param.UserData == selectedParams ? GUI.Style.Green : param.Style.TextColor;
|
param.TextColor = param.UserData == selectedParams ? GUI.Style.Green : param.Style.TextColor;
|
||||||
@@ -344,6 +359,7 @@ namespace Barotrauma
|
|||||||
editingSprite = null;
|
editingSprite = null;
|
||||||
UpdateParamsList();
|
UpdateParamsList();
|
||||||
UpdateRuinParamsList();
|
UpdateRuinParamsList();
|
||||||
|
UpdateCaveParamsList();
|
||||||
UpdateOutpostParamsList();
|
UpdateOutpostParamsList();
|
||||||
UpdateLevelObjectsList();
|
UpdateLevelObjectsList();
|
||||||
}
|
}
|
||||||
@@ -371,6 +387,22 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdateCaveParamsList()
|
||||||
|
{
|
||||||
|
editorContainer.ClearChildren();
|
||||||
|
caveParamsList.Content.ClearChildren();
|
||||||
|
|
||||||
|
foreach (CaveGenerationParams genParams in CaveGenerationParams.CaveParams)
|
||||||
|
{
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), caveParamsList.Content.RectTransform) { MinSize = new Point(0, 20) },
|
||||||
|
genParams.Name)
|
||||||
|
{
|
||||||
|
Padding = Vector4.Zero,
|
||||||
|
UserData = genParams
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdateRuinParamsList()
|
private void UpdateRuinParamsList()
|
||||||
{
|
{
|
||||||
editorContainer.ClearChildren();
|
editorContainer.ClearChildren();
|
||||||
@@ -425,6 +457,7 @@ namespace Barotrauma
|
|||||||
text: ToolBox.LimitString(levelObjPrefab.Name, GUI.SmallFont, paddedFrame.Rect.Width), textAlignment: Alignment.Center, font: GUI.SmallFont)
|
text: ToolBox.LimitString(levelObjPrefab.Name, GUI.SmallFont, paddedFrame.Rect.Width), textAlignment: Alignment.Center, font: GUI.SmallFont)
|
||||||
{
|
{
|
||||||
CanBeFocused = false,
|
CanBeFocused = false,
|
||||||
|
ToolTip = levelObjPrefab.Name
|
||||||
};
|
};
|
||||||
|
|
||||||
Sprite sprite = levelObjPrefab.Sprites.FirstOrDefault() ?? levelObjPrefab.DeformableSprite?.Sprite;
|
Sprite sprite = levelObjPrefab.Sprites.FirstOrDefault() ?? levelObjPrefab.DeformableSprite?.Sprite;
|
||||||
@@ -437,11 +470,10 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateLevelObjectEditor(LevelObjectPrefab levelObjectPrefab)
|
private void CreateCaveParamsEditor(CaveGenerationParams caveGenerationParams)
|
||||||
{
|
{
|
||||||
editorContainer.ClearChildren();
|
editorContainer.ClearChildren();
|
||||||
|
var editor = new SerializableEntityEditor(editorContainer.Content.RectTransform, caveGenerationParams, false, true, elementHeight: 20);
|
||||||
var editor = new SerializableEntityEditor(editorContainer.Content.RectTransform, levelObjectPrefab, false, true, elementHeight: 20, titleFont: GUI.LargeFont);
|
|
||||||
|
|
||||||
if (selectedParams != null)
|
if (selectedParams != null)
|
||||||
{
|
{
|
||||||
@@ -457,15 +489,60 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
MinValueFloat = 0,
|
MinValueFloat = 0,
|
||||||
MaxValueFloat = 100,
|
MaxValueFloat = 100,
|
||||||
FloatValue = levelObjectPrefab.GetCommonness(selectedParams.Identifier),
|
FloatValue = caveGenerationParams.GetCommonness(selectedParams),
|
||||||
OnValueChanged = (numberInput) =>
|
OnValueChanged = (numberInput) =>
|
||||||
{
|
{
|
||||||
levelObjectPrefab.OverrideCommonness[selectedParams.Identifier] = numberInput.FloatValue;
|
caveGenerationParams.OverrideCommonness[selectedParams.Identifier] = numberInput.FloatValue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), commonnessContainer.RectTransform), style: null);
|
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), commonnessContainer.RectTransform), style: null);
|
||||||
editor.AddCustomContent(commonnessContainer, 1);
|
editor.AddCustomContent(commonnessContainer, 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateLevelObjectEditor(LevelObjectPrefab levelObjectPrefab)
|
||||||
|
{
|
||||||
|
editorContainer.ClearChildren();
|
||||||
|
|
||||||
|
var editor = new SerializableEntityEditor(editorContainer.Content.RectTransform, levelObjectPrefab, false, true, elementHeight: 20, titleFont: GUI.LargeFont);
|
||||||
|
|
||||||
|
if (selectedParams != null)
|
||||||
|
{
|
||||||
|
List<string> availableIdentifiers = new List<string>();
|
||||||
|
{
|
||||||
|
if (selectedParams != null) { availableIdentifiers.Add(selectedParams.Identifier); }
|
||||||
|
}
|
||||||
|
foreach (var caveParam in CaveGenerationParams.CaveParams)
|
||||||
|
{
|
||||||
|
if (selectedParams != null && caveParam.GetCommonness(selectedParams) <= 0.0f) { continue; }
|
||||||
|
availableIdentifiers.Add(caveParam.Identifier);
|
||||||
|
}
|
||||||
|
availableIdentifiers.Reverse();
|
||||||
|
|
||||||
|
foreach (string paramsId in availableIdentifiers)
|
||||||
|
{
|
||||||
|
var commonnessContainer = new GUILayoutGroup(new RectTransform(new Point(editor.Rect.Width, 70)) { IsFixedSize = true },
|
||||||
|
isHorizontal: false, childAnchor: Anchor.TopCenter)
|
||||||
|
{
|
||||||
|
AbsoluteSpacing = 5,
|
||||||
|
Stretch = true
|
||||||
|
};
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.4f), commonnessContainer.RectTransform),
|
||||||
|
TextManager.GetWithVariable("leveleditor.levelobjcommonness", "[leveltype]", paramsId), textAlignment: Alignment.Center);
|
||||||
|
new GUINumberInput(new RectTransform(new Vector2(0.5f, 0.4f), commonnessContainer.RectTransform), GUINumberInput.NumberType.Float)
|
||||||
|
{
|
||||||
|
MinValueFloat = 0,
|
||||||
|
MaxValueFloat = 100,
|
||||||
|
FloatValue = selectedParams.Identifier == paramsId ? levelObjectPrefab.GetCommonness(selectedParams) : levelObjectPrefab.GetCommonness(CaveGenerationParams.CaveParams.Find(p => p.Identifier == paramsId)),
|
||||||
|
OnValueChanged = (numberInput) =>
|
||||||
|
{
|
||||||
|
levelObjectPrefab.OverrideCommonness[paramsId] = numberInput.FloatValue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), commonnessContainer.RectTransform), style: null);
|
||||||
|
editor.AddCustomContent(commonnessContainer, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Sprite sprite = levelObjectPrefab.Sprites.FirstOrDefault() ?? levelObjectPrefab.DeformableSprite?.Sprite;
|
Sprite sprite = levelObjectPrefab.Sprites.FirstOrDefault() ?? levelObjectPrefab.DeformableSprite?.Sprite;
|
||||||
if (sprite != null)
|
if (sprite != null)
|
||||||
@@ -508,7 +585,7 @@ namespace Barotrauma
|
|||||||
foreach (LevelObjectPrefab objPrefab in LevelObjectPrefab.List)
|
foreach (LevelObjectPrefab objPrefab in LevelObjectPrefab.List)
|
||||||
{
|
{
|
||||||
dropdown.AddItem(objPrefab.Name, objPrefab);
|
dropdown.AddItem(objPrefab.Name, objPrefab);
|
||||||
if (childObj.AllowedNames.Contains(objPrefab.Name)) dropdown.SelectItem(objPrefab);
|
if (childObj.AllowedNames.Contains(objPrefab.Name)) { dropdown.SelectItem(objPrefab); }
|
||||||
}
|
}
|
||||||
dropdown.OnSelected = (selected, obj) =>
|
dropdown.OnSelected = (selected, obj) =>
|
||||||
{
|
{
|
||||||
@@ -590,7 +667,7 @@ namespace Barotrauma
|
|||||||
foreach (GUIComponent levelObjFrame in levelObjectList.Content.Children)
|
foreach (GUIComponent levelObjFrame in levelObjectList.Content.Children)
|
||||||
{
|
{
|
||||||
var levelObj = levelObjFrame.UserData as LevelObjectPrefab;
|
var levelObj = levelObjFrame.UserData as LevelObjectPrefab;
|
||||||
float commonness = levelObj.GetCommonness(selectedParams.Identifier);
|
float commonness = levelObj.GetCommonness(selectedParams);
|
||||||
levelObjFrame.Color = commonness > 0.0f ? GUI.Style.Green * 0.4f : Color.Transparent;
|
levelObjFrame.Color = commonness > 0.0f ? GUI.Style.Green * 0.4f : Color.Transparent;
|
||||||
levelObjFrame.SelectedColor = commonness > 0.0f ? GUI.Style.Green * 0.6f : Color.White * 0.5f;
|
levelObjFrame.SelectedColor = commonness > 0.0f ? GUI.Style.Green * 0.6f : Color.White * 0.5f;
|
||||||
levelObjFrame.HoverColor = commonness > 0.0f ? GUI.Style.Green * 0.7f : Color.White * 0.6f;
|
levelObjFrame.HoverColor = commonness > 0.0f ? GUI.Style.Green * 0.7f : Color.White * 0.6f;
|
||||||
@@ -607,7 +684,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
var levelObj1 = c1.GUIComponent.UserData as LevelObjectPrefab;
|
var levelObj1 = c1.GUIComponent.UserData as LevelObjectPrefab;
|
||||||
var levelObj2 = c2.GUIComponent.UserData as LevelObjectPrefab;
|
var levelObj2 = c2.GUIComponent.UserData as LevelObjectPrefab;
|
||||||
return Math.Sign(levelObj2.GetCommonness(selectedParams.Identifier) - levelObj1.GetCommonness(selectedParams.Identifier));
|
return Math.Sign(levelObj2.GetCommonness(selectedParams) - levelObj1.GetCommonness(selectedParams));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -630,7 +707,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (lightingEnabled.Selected)
|
if (lightingEnabled.Selected)
|
||||||
{
|
{
|
||||||
GameMain.LightManager.UpdateLightMap(graphics, spriteBatch, cam);
|
GameMain.LightManager.RenderLightMap(graphics, spriteBatch, cam);
|
||||||
}
|
}
|
||||||
graphics.Clear(Color.Black);
|
graphics.Clear(Color.Black);
|
||||||
|
|
||||||
@@ -643,6 +720,72 @@ namespace Barotrauma
|
|||||||
Submarine.DrawFront(spriteBatch);
|
Submarine.DrawFront(spriteBatch);
|
||||||
Submarine.DrawDamageable(spriteBatch, null);
|
Submarine.DrawDamageable(spriteBatch, null);
|
||||||
GUI.DrawRectangle(spriteBatch, new Rectangle(new Point(0, -Level.Loaded.Size.Y), Level.Loaded.Size), Color.Gray, thickness: (int)(1.0f / cam.Zoom));
|
GUI.DrawRectangle(spriteBatch, new Rectangle(new Point(0, -Level.Loaded.Size.Y), Level.Loaded.Size), Color.Gray, thickness: (int)(1.0f / cam.Zoom));
|
||||||
|
|
||||||
|
for (int i = 0; i < Level.Loaded.Tunnels.Count; i++)
|
||||||
|
{
|
||||||
|
var tunnel = Level.Loaded.Tunnels[i];
|
||||||
|
Color tunnelColor = tunnelDebugColors[i % tunnelDebugColors.Length] * 0.2f;
|
||||||
|
for (int j = 1; j < tunnel.Nodes.Count; j++)
|
||||||
|
{
|
||||||
|
Vector2 start = new Vector2(tunnel.Nodes[j - 1].X, -tunnel.Nodes[j - 1].Y);
|
||||||
|
Vector2 end = new Vector2(tunnel.Nodes[j].X, -tunnel.Nodes[j].Y);
|
||||||
|
GUI.DrawLine(spriteBatch, start, end, tunnelColor, width: (int)(2.0f / cam.Zoom));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Level.InterestingPosition interestingPos in Level.Loaded.PositionsOfInterest)
|
||||||
|
{
|
||||||
|
if (interestingPos.Position.X < cam.WorldView.X || interestingPos.Position.X > cam.WorldView.Right ||
|
||||||
|
interestingPos.Position.Y > cam.WorldView.Y || interestingPos.Position.Y < cam.WorldView.Y - cam.WorldView.Height)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 pos = new Vector2(interestingPos.Position.X, -interestingPos.Position.Y);
|
||||||
|
spriteBatch.DrawCircle(pos, 500, 6, Color.White * 0.5f, thickness: (int)(2 / cam.Zoom));
|
||||||
|
GUI.DrawString(spriteBatch, pos, interestingPos.PositionType.ToString(), Color.White, font: GUI.LargeFont);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Improve this temporary level editor debug solution (or remove it)
|
||||||
|
foreach (var pathPoint in Level.Loaded.PathPoints)
|
||||||
|
{
|
||||||
|
Vector2 pathPointPos = new Vector2(pathPoint.Position.X, -pathPoint.Position.Y);
|
||||||
|
foreach (var location in pathPoint.ClusterLocations)
|
||||||
|
{
|
||||||
|
if (location.Resources == null) { continue; }
|
||||||
|
foreach (var resource in location.Resources)
|
||||||
|
{
|
||||||
|
Vector2 resourcePos = new Vector2(resource.Position.X, -resource.Position.Y);
|
||||||
|
spriteBatch.DrawCircle(resourcePos, 100, 6, Color.DarkGreen * 0.5f, thickness: (int)(2 / cam.Zoom));
|
||||||
|
GUI.DrawString(spriteBatch, resourcePos, resource.Name, Color.DarkGreen, font: GUI.LargeFont);
|
||||||
|
var dist = Vector2.Distance(resourcePos, pathPointPos);
|
||||||
|
var lineStartPos = Vector2.Lerp(resourcePos, pathPointPos, 110 / dist);
|
||||||
|
var lineEndPos = Vector2.Lerp(pathPointPos, resourcePos, 310 / dist);
|
||||||
|
GUI.DrawLine(spriteBatch, lineStartPos, lineEndPos, Color.DarkGreen * 0.5f, width: (int)(2 / cam.Zoom));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var color = pathPoint.ShouldContainResources ? Color.DarkGreen : Color.DarkRed;
|
||||||
|
spriteBatch.DrawCircle(pathPointPos, 300, 6, color * 0.5f, thickness: (int)(2 / cam.Zoom));
|
||||||
|
GUI.DrawString(spriteBatch, pathPointPos, "Path Point\n" + pathPoint.Id, color, font: GUI.LargeFont);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*for (int i = 0; i < Level.Loaded.distanceField.Count; i++)
|
||||||
|
{
|
||||||
|
GUI.DrawRectangle(spriteBatch,
|
||||||
|
new Vector2(Level.Loaded.distanceField[i].First.X, -Level.Loaded.distanceField[i].First.Y),
|
||||||
|
Vector2.One * 5 / cam.Zoom,
|
||||||
|
ToolBox.GradientLerp((float)(Level.Loaded.distanceField[i].Second / 20000.0), Color.Red, Color.Orange, Color.Yellow, Color.LightGreen),
|
||||||
|
isFilled: true);
|
||||||
|
}*/
|
||||||
|
/*for (int i = 0; i < Level.Loaded.siteCoordsX.Count; i++)
|
||||||
|
{
|
||||||
|
GUI.DrawRectangle(spriteBatch,
|
||||||
|
new Vector2((float)Level.Loaded.siteCoordsX[i], -(float)Level.Loaded.siteCoordsY[i]),
|
||||||
|
Vector2.One * 5 / cam.Zoom,
|
||||||
|
Color.Red,
|
||||||
|
isFilled: true);
|
||||||
|
}*/
|
||||||
|
|
||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
|
|
||||||
if (lightingEnabled.Selected)
|
if (lightingEnabled.Selected)
|
||||||
@@ -659,12 +802,23 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
|
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
|
||||||
|
if (Level.Loaded != null)
|
||||||
|
{
|
||||||
|
float crushDepthScreen = cam.WorldToScreen(new Vector2(0.0f, -Level.Loaded.CrushDepth)).Y;
|
||||||
|
if (crushDepthScreen > 0.0f && crushDepthScreen < GameMain.GraphicsHeight)
|
||||||
|
{
|
||||||
|
GUI.DrawLine(spriteBatch, new Vector2(0, crushDepthScreen), new Vector2(GameMain.GraphicsWidth, crushDepthScreen), GUI.Style.Red * 0.25f, width: 5);
|
||||||
|
GUI.DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth / 2, crushDepthScreen), "Crush depth", GUI.Style.Red, backgroundColor: Color.Black);
|
||||||
|
}
|
||||||
|
}
|
||||||
GUI.Draw(Cam, spriteBatch);
|
GUI.Draw(Cam, spriteBatch);
|
||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update(double deltaTime)
|
public override void Update(double deltaTime)
|
||||||
{
|
{
|
||||||
|
GameMain.LightManager?.Update((float)deltaTime);
|
||||||
|
|
||||||
pointerLightSource.Position = cam.ScreenToWorld(PlayerInput.MousePosition);
|
pointerLightSource.Position = cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||||
pointerLightSource.Enabled = cursorLightEnabled.Selected;
|
pointerLightSource.Enabled = cursorLightEnabled.Selected;
|
||||||
pointerLightSource.IsBackground = true;
|
pointerLightSource.IsBackground = true;
|
||||||
@@ -694,7 +848,40 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
foreach (XElement element in doc.Root.Elements())
|
foreach (XElement element in doc.Root.Elements())
|
||||||
{
|
{
|
||||||
XElement levelParamElement = element;
|
if (element.IsOverride())
|
||||||
|
{
|
||||||
|
foreach (XElement subElement in element.Elements())
|
||||||
|
{
|
||||||
|
string id = element.GetAttributeString("identifier", null) ?? element.Name.ToString();
|
||||||
|
if (!id.Equals(genParams.Name, StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||||
|
SerializableProperty.SerializeProperties(genParams, element, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string id = element.GetAttributeString("identifier", null) ?? element.Name.ToString();
|
||||||
|
if (!id.Equals(genParams.Name, StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||||
|
SerializableProperty.SerializeProperties(genParams, element, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
using (var writer = XmlWriter.Create(configFile.Path, settings))
|
||||||
|
{
|
||||||
|
doc.WriteTo(writer);
|
||||||
|
writer.Flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (ContentFile configFile in GameMain.Instance.GetFilesOfType(ContentType.CaveGenerationParameters))
|
||||||
|
{
|
||||||
|
XDocument doc = XMLExtensions.TryLoadXml(configFile.Path);
|
||||||
|
if (doc == null) { continue; }
|
||||||
|
|
||||||
|
foreach (CaveGenerationParams genParams in CaveGenerationParams.CaveParams)
|
||||||
|
{
|
||||||
|
foreach (XElement element in doc.Root.Elements())
|
||||||
|
{
|
||||||
if (element.IsOverride())
|
if (element.IsOverride())
|
||||||
{
|
{
|
||||||
foreach (XElement subElement in element.Elements())
|
foreach (XElement subElement in element.Elements())
|
||||||
@@ -730,7 +917,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
foreach (XElement element in doc.Root.Elements())
|
foreach (XElement element in doc.Root.Elements())
|
||||||
{
|
{
|
||||||
if (!element.Name.ToString().Equals(levelObjPrefab.Name, StringComparison.OrdinalIgnoreCase)) { continue; }
|
string identifier = element.GetAttributeString("identifier", null);
|
||||||
|
if (!identifier.Equals(levelObjPrefab.Identifier, StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||||
levelObjPrefab.Save(element);
|
levelObjPrefab.Save(element);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -846,7 +1034,7 @@ namespace Barotrauma
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LevelObjectPrefab.List.Any(obj => obj.Name.ToLower() == nameBox.Text.ToLower()))
|
if (LevelObjectPrefab.List.Any(obj => obj.Identifier.Equals(nameBox.Text, StringComparison.OrdinalIgnoreCase)))
|
||||||
{
|
{
|
||||||
nameBox.Flash(GUI.Style.Red);
|
nameBox.Flash(GUI.Style.Red);
|
||||||
GUI.AddMessage(TextManager.Get("leveleditor.levelobjnametaken"), GUI.Style.Red);
|
GUI.AddMessage(TextManager.Get("leveleditor.levelobjnametaken"), GUI.Style.Red);
|
||||||
@@ -860,14 +1048,14 @@ namespace Barotrauma
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
newPrefab.Name = nameBox.Text;
|
newPrefab.Identifier = nameBox.Text;
|
||||||
|
|
||||||
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings { Indent = true };
|
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings { Indent = true };
|
||||||
foreach (ContentFile configFile in GameMain.Instance.GetFilesOfType(ContentType.LevelObjectPrefabs))
|
foreach (ContentFile configFile in GameMain.Instance.GetFilesOfType(ContentType.LevelObjectPrefabs))
|
||||||
{
|
{
|
||||||
XDocument doc = XMLExtensions.TryLoadXml(configFile.Path);
|
XDocument doc = XMLExtensions.TryLoadXml(configFile.Path);
|
||||||
if (doc == null) { continue; }
|
if (doc == null) { continue; }
|
||||||
var newElement = new XElement(newPrefab.Name);
|
var newElement = new XElement(newPrefab.Identifier);
|
||||||
newPrefab.Save(newElement);
|
newPrefab.Save(newElement);
|
||||||
newElement.Add(new XElement("Sprite",
|
newElement.Add(new XElement("Sprite",
|
||||||
new XAttribute("texture", texturePathBox.Text),
|
new XAttribute("texture", texturePathBox.Text),
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ namespace Barotrauma
|
|||||||
private GUIImage playstyleBanner;
|
private GUIImage playstyleBanner;
|
||||||
private GUITextBlock playstyleDescription;
|
private GUITextBlock playstyleDescription;
|
||||||
|
|
||||||
|
private GUIComponent remoteContentContainer;
|
||||||
|
private XDocument remoteContentDoc;
|
||||||
|
|
||||||
private Tab selectedTab;
|
private Tab selectedTab;
|
||||||
|
|
||||||
private Sprite backgroundSprite;
|
private Sprite backgroundSprite;
|
||||||
@@ -62,6 +65,14 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
CreateHostServerFields();
|
CreateHostServerFields();
|
||||||
CreateCampaignSetupUI();
|
CreateCampaignSetupUI();
|
||||||
|
if (remoteContentDoc?.Root != null)
|
||||||
|
{
|
||||||
|
remoteContentContainer.ClearChildren();
|
||||||
|
foreach (XElement subElement in remoteContentDoc.Root.Elements())
|
||||||
|
{
|
||||||
|
GUIComponent.FromXML(subElement, remoteContentContainer.RectTransform);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
new GUIImage(new RectTransform(new Vector2(0.4f, 0.25f), Frame.RectTransform, Anchor.BottomRight)
|
new GUIImage(new RectTransform(new Vector2(0.4f, 0.25f), Frame.RectTransform, Anchor.BottomRight)
|
||||||
@@ -84,6 +95,11 @@ namespace Barotrauma
|
|||||||
RelativeSpacing = 0.02f
|
RelativeSpacing = 0.02f
|
||||||
};
|
};
|
||||||
|
|
||||||
|
remoteContentContainer = new GUIFrame(new RectTransform(Vector2.One, parent: Frame.RectTransform), style: null)
|
||||||
|
{
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
|
||||||
#if TEST_REMOTE_CONTENT
|
#if TEST_REMOTE_CONTENT
|
||||||
|
|
||||||
var doc = XMLExtensions.TryLoadXml("Content/UI/MenuTextTest.xml");
|
var doc = XMLExtensions.TryLoadXml("Content/UI/MenuTextTest.xml");
|
||||||
@@ -91,7 +107,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
foreach (XElement subElement in doc?.Root.Elements())
|
foreach (XElement subElement in doc?.Root.Elements())
|
||||||
{
|
{
|
||||||
GUIComponent.FromXML(subElement, Frame.RectTransform);
|
GUIComponent.FromXML(subElement, remoteContentContainer.RectTransform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@@ -1402,10 +1418,10 @@ namespace Barotrauma
|
|||||||
if (index > 0) { xml = xml.Substring(index, xml.Length - index); }
|
if (index > 0) { xml = xml.Substring(index, xml.Length - index); }
|
||||||
if (!string.IsNullOrWhiteSpace(xml))
|
if (!string.IsNullOrWhiteSpace(xml))
|
||||||
{
|
{
|
||||||
XElement element = XDocument.Parse(xml)?.Root;
|
remoteContentDoc = XDocument.Parse(xml);
|
||||||
foreach (XElement subElement in element.Elements())
|
foreach (XElement subElement in remoteContentDoc?.Root.Elements())
|
||||||
{
|
{
|
||||||
GUIComponent.FromXML(subElement, Frame.RectTransform);
|
GUIComponent.FromXML(subElement, remoteContentContainer.RectTransform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -910,15 +910,17 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
missionTypeTickBoxes = new GUITickBox[Enum.GetValues(typeof(MissionType)).Length - 2];
|
var missionTypes = (MissionType[])Enum.GetValues(typeof(MissionType));
|
||||||
|
missionTypeTickBoxes = new GUITickBox[missionTypes.Length - 2];
|
||||||
int index = 0;
|
int index = 0;
|
||||||
foreach (MissionType missionType in Enum.GetValues(typeof(MissionType)))
|
for (int i = 0; i < missionTypes.Length; i++)
|
||||||
{
|
{
|
||||||
|
var missionType = missionTypes[i];
|
||||||
if (missionType == MissionType.None || missionType == MissionType.All) { continue; }
|
if (missionType == MissionType.None || missionType == MissionType.All) { continue; }
|
||||||
|
|
||||||
GUIFrame frame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), missionTypeList.Content.RectTransform) { MinSize = new Point(0, (int)(30 * GUI.Scale)) }, style: "ListBoxElement")
|
GUIFrame frame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), missionTypeList.Content.RectTransform) { MinSize = new Point(0, (int)(30 * GUI.Scale)) }, style: "ListBoxElement")
|
||||||
{
|
{
|
||||||
UserData = index,
|
UserData = missionType,
|
||||||
};
|
};
|
||||||
|
|
||||||
missionTypeTickBoxes[index] = new GUITickBox(new RectTransform(Vector2.One, frame.RectTransform),
|
missionTypeTickBoxes[index] = new GUITickBox(new RectTransform(Vector2.One, frame.RectTransform),
|
||||||
@@ -934,7 +936,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
frame.RectTransform.MinSize = missionTypeTickBoxes[index].RectTransform.MinSize;
|
frame.RectTransform.MinSize = missionTypeTickBoxes[index].RectTransform.MinSize;
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
clientDisabledElements.AddRange(missionTypeTickBoxes);
|
clientDisabledElements.AddRange(missionTypeTickBoxes);
|
||||||
@@ -2509,7 +2510,7 @@ namespace Barotrauma
|
|||||||
Selected = info.Gender == Gender.Female
|
Selected = info.Gender == Gender.Female
|
||||||
};
|
};
|
||||||
|
|
||||||
int hairCount = info.FilterByTypeAndHeadID(info.FilterElementsByGenderAndRace(info.Wearables), WearableType.Hair).Count();
|
int hairCount = info.FilterByTypeAndHeadID(info.FilterElementsByGenderAndRace(info.Wearables, info.Head.gender, info.Head.race), WearableType.Hair, info.HeadSpriteId).Count();
|
||||||
if (hairCount > 0)
|
if (hairCount > 0)
|
||||||
{
|
{
|
||||||
var label = new GUITextBlock(new RectTransform(elementSize, content.RectTransform), TextManager.Get("FaceAttachment.Hair"), font: GUI.SubHeadingFont);
|
var label = new GUITextBlock(new RectTransform(elementSize, content.RectTransform), TextManager.Get("FaceAttachment.Hair"), font: GUI.SubHeadingFont);
|
||||||
@@ -2524,7 +2525,7 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
int beardCount = info.FilterByTypeAndHeadID(info.FilterElementsByGenderAndRace(info.Wearables), WearableType.Beard).Count();
|
int beardCount = info.FilterByTypeAndHeadID(info.FilterElementsByGenderAndRace(info.Wearables, info.Head.gender, info.Head.race), WearableType.Beard, info.HeadSpriteId).Count();
|
||||||
if (beardCount > 0)
|
if (beardCount > 0)
|
||||||
{
|
{
|
||||||
var label = new GUITextBlock(new RectTransform(elementSize, content.RectTransform), TextManager.Get("FaceAttachment.Beard"), font: GUI.SubHeadingFont);
|
var label = new GUITextBlock(new RectTransform(elementSize, content.RectTransform), TextManager.Get("FaceAttachment.Beard"), font: GUI.SubHeadingFont);
|
||||||
@@ -2539,7 +2540,7 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
int moustacheCount = info.FilterByTypeAndHeadID(info.FilterElementsByGenderAndRace(info.Wearables), WearableType.Moustache).Count();
|
int moustacheCount = info.FilterByTypeAndHeadID(info.FilterElementsByGenderAndRace(info.Wearables, info.Head.gender, info.Head.race), WearableType.Moustache, info.HeadSpriteId).Count();
|
||||||
if (moustacheCount > 0)
|
if (moustacheCount > 0)
|
||||||
{
|
{
|
||||||
var label = new GUITextBlock(new RectTransform(elementSize, content.RectTransform), TextManager.Get("FaceAttachment.Moustache"), font: GUI.SubHeadingFont);
|
var label = new GUITextBlock(new RectTransform(elementSize, content.RectTransform), TextManager.Get("FaceAttachment.Moustache"), font: GUI.SubHeadingFont);
|
||||||
@@ -2554,7 +2555,7 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
int faceAttachmentCount = info.FilterByTypeAndHeadID(info.FilterElementsByGenderAndRace(info.Wearables), WearableType.FaceAttachment).Count();
|
int faceAttachmentCount = info.FilterByTypeAndHeadID(info.FilterElementsByGenderAndRace(info.Wearables, info.Head.gender, info.Head.race), WearableType.FaceAttachment, info.HeadSpriteId).Count();
|
||||||
if (faceAttachmentCount > 0)
|
if (faceAttachmentCount > 0)
|
||||||
{
|
{
|
||||||
var label = new GUITextBlock(new RectTransform(elementSize, content.RectTransform), TextManager.Get("FaceAttachment.Accessories"), font: GUI.SubHeadingFont);
|
var label = new GUITextBlock(new RectTransform(elementSize, content.RectTransform), TextManager.Get("FaceAttachment.Accessories"), font: GUI.SubHeadingFont);
|
||||||
@@ -3001,16 +3002,33 @@ namespace Barotrauma
|
|||||||
RefreshGameModeContent();
|
RefreshGameModeContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void RefreshMissionTypes()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < missionTypeTickBoxes.Length; i++)
|
||||||
|
{
|
||||||
|
MissionType missionType = (MissionType)((int)missionTypeTickBoxes[i].UserData);
|
||||||
|
if (SelectedMode == GameModePreset.Mission)
|
||||||
|
{
|
||||||
|
missionTypeTickBoxes[i].Parent.Visible = MissionPrefab.CoOpMissionClasses.ContainsKey(missionType);
|
||||||
|
}
|
||||||
|
else if (SelectedMode == GameModePreset.PvP)
|
||||||
|
{
|
||||||
|
missionTypeTickBoxes[i].Parent.Visible = MissionPrefab.PvPMissionClasses.ContainsKey(missionType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void RefreshGameModeContent()
|
private void RefreshGameModeContent()
|
||||||
{
|
{
|
||||||
if (GameMain.Client == null) { return; }
|
if (GameMain.Client == null) { return; }
|
||||||
|
|
||||||
autoRestartBox.Parent.Visible = true;
|
autoRestartBox.Parent.Visible = true;
|
||||||
settingsBlocker.Visible = false;
|
settingsBlocker.Visible = false;
|
||||||
if (SelectedMode == GameModePreset.Mission)
|
if (SelectedMode == GameModePreset.Mission || SelectedMode == GameModePreset.PvP)
|
||||||
{
|
{
|
||||||
MissionTypeFrame.Visible = true;
|
MissionTypeFrame.Visible = true;
|
||||||
CampaignFrame.Visible = CampaignSetupFrame.Visible = false;
|
CampaignFrame.Visible = CampaignSetupFrame.Visible = false;
|
||||||
|
RefreshMissionTypes();
|
||||||
}
|
}
|
||||||
else if (SelectedMode == GameModePreset.MultiPlayerCampaign)
|
else if (SelectedMode == GameModePreset.MultiPlayerCampaign)
|
||||||
{
|
{
|
||||||
@@ -3062,7 +3080,7 @@ namespace Barotrauma
|
|||||||
RefreshEnabledElements();
|
RefreshEnabledElements();
|
||||||
if (enabled)
|
if (enabled)
|
||||||
{
|
{
|
||||||
modeList.Select(2, true);
|
modeList.Select(GameModePreset.MultiPlayerCampaign, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
var temp = LoadException;
|
var temp = LoadException;
|
||||||
LoadException = null;
|
LoadException = null;
|
||||||
throw temp;
|
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(temp).Throw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1061,7 +1061,7 @@ namespace Barotrauma
|
|||||||
(!filterFull.Selected || serverInfo.PlayerCount < serverInfo.MaxPlayers) &&
|
(!filterFull.Selected || serverInfo.PlayerCount < serverInfo.MaxPlayers) &&
|
||||||
(!filterEmpty.Selected || serverInfo.PlayerCount > 0) &&
|
(!filterEmpty.Selected || serverInfo.PlayerCount > 0) &&
|
||||||
(!filterWhitelisted.Selected || serverInfo.UsingWhiteList == true) &&
|
(!filterWhitelisted.Selected || serverInfo.UsingWhiteList == true) &&
|
||||||
(filterOffensive.Selected || !ForbiddenWordFilter.IsForbidden(serverInfo.ServerName)) &&
|
(!filterOffensive.Selected || !ForbiddenWordFilter.IsForbidden(serverInfo.ServerName)) &&
|
||||||
(!filterKarma.Selected || serverInfo.KarmaEnabled == true) &&
|
(!filterKarma.Selected || serverInfo.KarmaEnabled == true) &&
|
||||||
(!filterFriendlyFire.Selected || serverInfo.FriendlyFireEnabled == false) &&
|
(!filterFriendlyFire.Selected || serverInfo.FriendlyFireEnabled == false) &&
|
||||||
(!filterTraitor.Selected || serverInfo.TraitorsEnabled == YesNoMaybe.Yes || serverInfo.TraitorsEnabled == YesNoMaybe.Maybe) &&
|
(!filterTraitor.Selected || serverInfo.TraitorsEnabled == YesNoMaybe.Yes || serverInfo.TraitorsEnabled == YesNoMaybe.Maybe) &&
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private bool entityMenuOpen = true;
|
private bool entityMenuOpen = true;
|
||||||
private float entityMenuOpenState = 1.0f;
|
private float entityMenuOpenState = 1.0f;
|
||||||
|
private string lastFilter;
|
||||||
public GUIComponent EntityMenu;
|
public GUIComponent EntityMenu;
|
||||||
private GUITextBox entityFilterBox;
|
private GUITextBox entityFilterBox;
|
||||||
private GUIListBox entityList;
|
private GUIListBox entityList;
|
||||||
@@ -105,7 +106,23 @@ namespace Barotrauma
|
|||||||
private static GUIComponent autoSaveLabel;
|
private static GUIComponent autoSaveLabel;
|
||||||
private static int maxAutoSaves = GameSettings.MaximumAutoSaves;
|
private static int maxAutoSaves = GameSettings.MaximumAutoSaves;
|
||||||
|
|
||||||
public static bool BulkItemBufferInUse;
|
public static readonly object ItemAddMutex = new object(), ItemRemoveMutex = new object();
|
||||||
|
|
||||||
|
private static object bulkItemBufferinUse;
|
||||||
|
|
||||||
|
public static object BulkItemBufferInUse
|
||||||
|
{
|
||||||
|
get => bulkItemBufferinUse;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != bulkItemBufferinUse && bulkItemBufferinUse != null)
|
||||||
|
{
|
||||||
|
CommitBulkItemBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
bulkItemBufferinUse = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
public static List<AddOrDeleteCommand> BulkItemBuffer = new List<AddOrDeleteCommand>();
|
public static List<AddOrDeleteCommand> BulkItemBuffer = new List<AddOrDeleteCommand>();
|
||||||
|
|
||||||
public static List<WarningType> SuppressedWarnings = new List<WarningType>();
|
public static List<WarningType> SuppressedWarnings = new List<WarningType>();
|
||||||
@@ -630,35 +647,33 @@ namespace Barotrauma
|
|||||||
return Structure.WallList.Count.ToString();
|
return Structure.WallList.Count.ToString();
|
||||||
};
|
};
|
||||||
|
|
||||||
var lightCountText = new GUITextBlock(new RectTransform(new Vector2(0.75f, 0.0f), paddedEntityCountPanel.RectTransform), TextManager.Get("SubEditorLights"),
|
var lightCountLabel = new GUITextBlock(new RectTransform(new Vector2(0.75f, 0.0f), paddedEntityCountPanel.RectTransform), TextManager.Get("SubEditorLights"),
|
||||||
textAlignment: Alignment.CenterLeft, font: GUI.SmallFont);
|
textAlignment: Alignment.CenterLeft, font: GUI.SmallFont);
|
||||||
var lightCount = new GUITextBlock(new RectTransform(new Vector2(0.33f, 1.0f), lightCountText.RectTransform, Anchor.TopRight, Pivot.TopLeft), "", textAlignment: Alignment.CenterRight);
|
var lightCountText = new GUITextBlock(new RectTransform(new Vector2(0.33f, 1.0f), lightCountLabel.RectTransform, Anchor.TopRight, Pivot.TopLeft), "", textAlignment: Alignment.CenterRight);
|
||||||
lightCount.TextGetter = () =>
|
lightCountText.TextGetter = () =>
|
||||||
{
|
{
|
||||||
int disabledItemLightCount = 0;
|
int lightCount = 0;
|
||||||
foreach (Item item in Item.ItemList)
|
foreach (Item item in Item.ItemList)
|
||||||
{
|
{
|
||||||
if (item.ParentInventory == null) { continue; }
|
if (item.ParentInventory != null) { continue; }
|
||||||
disabledItemLightCount += item.GetComponents<LightComponent>().Count();
|
lightCount += item.GetComponents<LightComponent>().Count();
|
||||||
}
|
}
|
||||||
int count = GameMain.LightManager.Lights.Count() - disabledItemLightCount;
|
lightCountText.TextColor = ToolBox.GradientLerp(lightCount / 250.0f, GUI.Style.Green, GUI.Style.Orange, GUI.Style.Red);
|
||||||
lightCount.TextColor = ToolBox.GradientLerp(count / 250.0f, GUI.Style.Green, GUI.Style.Orange, GUI.Style.Red);
|
return lightCount.ToString();
|
||||||
return count.ToString();
|
|
||||||
};
|
};
|
||||||
var shadowCastingLightCountText = new GUITextBlock(new RectTransform(new Vector2(0.75f, 0.0f), paddedEntityCountPanel.RectTransform), TextManager.Get("SubEditorShadowCastingLights"),
|
var shadowCastingLightCountLabel = new GUITextBlock(new RectTransform(new Vector2(0.75f, 0.0f), paddedEntityCountPanel.RectTransform), TextManager.Get("SubEditorShadowCastingLights"),
|
||||||
textAlignment: Alignment.CenterLeft, font: GUI.SmallFont, wrap: true);
|
textAlignment: Alignment.CenterLeft, font: GUI.SmallFont, wrap: true);
|
||||||
var shadowCastingLightCount = new GUITextBlock(new RectTransform(new Vector2(0.33f, 1.0f), shadowCastingLightCountText.RectTransform, Anchor.TopRight, Pivot.TopLeft), "", textAlignment: Alignment.CenterRight);
|
var shadowCastingLightCountText = new GUITextBlock(new RectTransform(new Vector2(0.33f, 1.0f), shadowCastingLightCountLabel.RectTransform, Anchor.TopRight, Pivot.TopLeft), "", textAlignment: Alignment.CenterRight);
|
||||||
shadowCastingLightCount.TextGetter = () =>
|
shadowCastingLightCountText.TextGetter = () =>
|
||||||
{
|
{
|
||||||
int disabledItemLightCount = 0;
|
int lightCount = 0;
|
||||||
foreach (Item item in Item.ItemList)
|
foreach (Item item in Item.ItemList)
|
||||||
{
|
{
|
||||||
if (item.ParentInventory == null) { continue; }
|
if (item.ParentInventory != null) { continue; }
|
||||||
disabledItemLightCount += item.GetComponents<LightComponent>().Count();
|
lightCount += item.GetComponents<LightComponent>().Count(l => l.CastShadows);
|
||||||
}
|
}
|
||||||
int count = GameMain.LightManager.Lights.Count(l => l.CastShadows) - disabledItemLightCount;
|
shadowCastingLightCountText.TextColor = ToolBox.GradientLerp(lightCount / 60.0f, GUI.Style.Green, GUI.Style.Orange, GUI.Style.Red);
|
||||||
shadowCastingLightCount.TextColor = ToolBox.GradientLerp(count / 60.0f, GUI.Style.Green, GUI.Style.Orange, GUI.Style.Red);
|
return lightCount.ToString();
|
||||||
return count.ToString();
|
|
||||||
};
|
};
|
||||||
entityCountPanel.RectTransform.NonScaledSize =
|
entityCountPanel.RectTransform.NonScaledSize =
|
||||||
new Point(
|
new Point(
|
||||||
@@ -737,7 +752,13 @@ namespace Barotrauma
|
|||||||
var filterText = new GUITextBlock(new RectTransform(new Vector2(0.1f, 1.0f), entityMenuTop.RectTransform), TextManager.Get("serverlog.filter"), font: GUI.SubHeadingFont);
|
var filterText = new GUITextBlock(new RectTransform(new Vector2(0.1f, 1.0f), entityMenuTop.RectTransform), TextManager.Get("serverlog.filter"), font: GUI.SubHeadingFont);
|
||||||
filterText.RectTransform.MaxSize = new Point((int)(filterText.TextSize.X * 1.5f), int.MaxValue);
|
filterText.RectTransform.MaxSize = new Point((int)(filterText.TextSize.X * 1.5f), int.MaxValue);
|
||||||
entityFilterBox = new GUITextBox(new RectTransform(new Vector2(0.17f, 1.0f), entityMenuTop.RectTransform), font: GUI.Font, createClearButton: true);
|
entityFilterBox = new GUITextBox(new RectTransform(new Vector2(0.17f, 1.0f), entityMenuTop.RectTransform), font: GUI.Font, createClearButton: true);
|
||||||
entityFilterBox.OnTextChanged += (textBox, text) => { FilterEntities(text); return true; };
|
entityFilterBox.OnTextChanged += (textBox, text) =>
|
||||||
|
{
|
||||||
|
if (text == lastFilter) { return true; }
|
||||||
|
lastFilter = text;
|
||||||
|
FilterEntities(text);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
//spacing
|
//spacing
|
||||||
new GUIFrame(new RectTransform(new Vector2(0.075f, 1.0f), entityMenuTop.RectTransform), style: null);
|
new GUIFrame(new RectTransform(new Vector2(0.075f, 1.0f), entityMenuTop.RectTransform), style: null);
|
||||||
@@ -994,8 +1015,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
GameMain.LightManager.AmbientLight =
|
GameMain.LightManager.AmbientLight =
|
||||||
Level.Loaded?.GenerationParams?.AmbientLightColor ??
|
Level.Loaded?.GenerationParams?.AmbientLightColor ??
|
||||||
LevelGenerationParams.LevelParams?.FirstOrDefault()?.AmbientLightColor ??
|
new Color(3, 3, 3, 3);
|
||||||
new Color(20, 20, 20, 255);
|
|
||||||
|
|
||||||
UpdateEntityList();
|
UpdateEntityList();
|
||||||
if (!wasSelectedBefore)
|
if (!wasSelectedBefore)
|
||||||
@@ -1150,7 +1170,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (dummyCharacter != null) RemoveDummyCharacter();
|
if (dummyCharacter != null) RemoveDummyCharacter();
|
||||||
|
|
||||||
dummyCharacter = Character.Create(CharacterPrefab.HumanSpeciesName, Vector2.Zero, "", hasAi: false);
|
dummyCharacter = Character.Create(CharacterPrefab.HumanSpeciesName, Vector2.Zero, "", id: Entity.RespawnManagerID, hasAi: false);
|
||||||
dummyCharacter.Info.Name = "Galldren";
|
dummyCharacter.Info.Name = "Galldren";
|
||||||
|
|
||||||
//make space for the entity menu
|
//make space for the entity menu
|
||||||
@@ -1853,6 +1873,10 @@ namespace Barotrauma
|
|||||||
Submarine.MainSub.Info.Price = numberInput.IntValue;
|
Submarine.MainSub.Info.Price = numberInput.IntValue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
if (Submarine.MainSub?.Info != null)
|
||||||
|
{
|
||||||
|
Submarine.MainSub.Info.Price = Math.Max(Submarine.MainSub.Info.Price, basePrice);
|
||||||
|
}
|
||||||
|
|
||||||
if (!Submarine.MainSub.Info.HasTag(SubmarineTag.Shuttle))
|
if (!Submarine.MainSub.Info.HasTag(SubmarineTag.Shuttle))
|
||||||
{
|
{
|
||||||
@@ -2665,7 +2689,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
foreach (GUIComponent child in entityList.Content.Children)
|
foreach (GUIComponent child in entityList.Content.Children)
|
||||||
{
|
{
|
||||||
child.Visible = !entityCategory.HasValue || ((MapEntityPrefab) child.UserData).Category == entityCategory;
|
child.Visible = !entityCategory.HasValue || ((MapEntityPrefab) child.UserData).Category.HasFlag(entityCategory);
|
||||||
if (child.Visible && dummyCharacter?.SelectedConstruction?.OwnInventory != null)
|
if (child.Visible && dummyCharacter?.SelectedConstruction?.OwnInventory != null)
|
||||||
{
|
{
|
||||||
child.Visible = child.UserData is MapEntityPrefab item && IsItemPrefab(item);
|
child.Visible = child.UserData is MapEntityPrefab item && IsItemPrefab(item);
|
||||||
@@ -3710,6 +3734,24 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void CommitBulkItemBuffer()
|
||||||
|
{
|
||||||
|
if (BulkItemBuffer.Any())
|
||||||
|
{
|
||||||
|
AddOrDeleteCommand master = BulkItemBuffer[0];
|
||||||
|
for (int i = 1; i < BulkItemBuffer.Count; i++)
|
||||||
|
{
|
||||||
|
AddOrDeleteCommand command = BulkItemBuffer[i];
|
||||||
|
command.MergeInto(master);
|
||||||
|
}
|
||||||
|
|
||||||
|
StoreCommand(master);
|
||||||
|
BulkItemBuffer.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bulkItemBufferinUse = null;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Allows the game to run logic such as updating the world,
|
/// Allows the game to run logic such as updating the world,
|
||||||
/// checking for collisions, gathering input, and playing audio.
|
/// checking for collisions, gathering input, and playing audio.
|
||||||
@@ -3939,6 +3981,11 @@ namespace Barotrauma
|
|||||||
CloseItem();
|
CloseItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lightingEnabled)
|
||||||
|
{
|
||||||
|
GameMain.LightManager?.Update((float)deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
if (contextMenu != null)
|
if (contextMenu != null)
|
||||||
{
|
{
|
||||||
Rectangle expandedRect = contextMenu.Rect;
|
Rectangle expandedRect = contextMenu.Rect;
|
||||||
@@ -4034,7 +4081,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
// Deposit item from our "infinite stack" into inventory slots
|
// Deposit item from our "infinite stack" into inventory slots
|
||||||
var inv = dummyCharacter?.SelectedConstruction?.OwnInventory;
|
var inv = dummyCharacter?.SelectedConstruction?.OwnInventory;
|
||||||
if (inv?.slots != null)
|
if (inv?.slots != null && !PlayerInput.IsCtrlDown())
|
||||||
{
|
{
|
||||||
var dragginMouse = MouseDragStart != Vector2.Zero && Vector2.Distance(PlayerInput.MousePosition, MouseDragStart) >= GUI.Scale * 20;
|
var dragginMouse = MouseDragStart != Vector2.Zero && Vector2.Distance(PlayerInput.MousePosition, MouseDragStart) >= GUI.Scale * 20;
|
||||||
|
|
||||||
@@ -4090,7 +4137,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (!newItem.Removed)
|
if (!newItem.Removed)
|
||||||
{
|
{
|
||||||
BulkItemBufferInUse = true;
|
BulkItemBufferInUse = ItemAddMutex;
|
||||||
BulkItemBuffer.Add(new AddOrDeleteCommand(new List<MapEntity> { newItem }, false));
|
BulkItemBuffer.Add(new AddOrDeleteCommand(new List<MapEntity> { newItem }, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4162,7 +4209,7 @@ namespace Barotrauma
|
|||||||
List<MapEntity> placedEntities = itemInstance.Where(it => !it.Removed).Cast<MapEntity>().ToList();
|
List<MapEntity> placedEntities = itemInstance.Where(it => !it.Removed).Cast<MapEntity>().ToList();
|
||||||
if (placedEntities.Any())
|
if (placedEntities.Any())
|
||||||
{
|
{
|
||||||
BulkItemBufferInUse = true;
|
BulkItemBufferInUse = ItemAddMutex;
|
||||||
BulkItemBuffer.Add(new AddOrDeleteCommand(placedEntities, false));
|
BulkItemBuffer.Add(new AddOrDeleteCommand(placedEntities, false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4174,18 +4221,9 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BulkItemBufferInUse && PlayerInput.PrimaryMouseButtonReleased() && BulkItemBuffer.Any())
|
if (PlayerInput.PrimaryMouseButtonReleased() && BulkItemBufferInUse != null)
|
||||||
{
|
{
|
||||||
AddOrDeleteCommand master = BulkItemBuffer[0];
|
CommitBulkItemBuffer();
|
||||||
for (int i = 1; i < BulkItemBuffer.Count; i++)
|
|
||||||
{
|
|
||||||
AddOrDeleteCommand command = BulkItemBuffer[i];
|
|
||||||
command.MergeInto(master);
|
|
||||||
}
|
|
||||||
|
|
||||||
StoreCommand(master);
|
|
||||||
BulkItemBuffer.Clear();
|
|
||||||
BulkItemBufferInUse = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SerializableEntityEditor.PropertyChangesActive && (SerializableEntityEditor.NextCommandPush < DateTime.Now || MapEntity.EditingHUD == null))
|
if (SerializableEntityEditor.PropertyChangesActive && (SerializableEntityEditor.NextCommandPush < DateTime.Now || MapEntity.EditingHUD == null))
|
||||||
@@ -4326,7 +4364,7 @@ namespace Barotrauma
|
|||||||
cam.UpdateTransform();
|
cam.UpdateTransform();
|
||||||
if (lightingEnabled)
|
if (lightingEnabled)
|
||||||
{
|
{
|
||||||
GameMain.LightManager.UpdateLightMap(graphics, spriteBatch, cam);
|
GameMain.LightManager.RenderLightMap(graphics, spriteBatch, cam);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Submarine sub in Submarine.Loaded)
|
foreach (Submarine sub in Submarine.Loaded)
|
||||||
@@ -4493,6 +4531,7 @@ namespace Barotrauma
|
|||||||
stream.Dispose();
|
stream.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsSubEditor() { return Screen.Selected is SubEditorScreen && !Submarine.Unloading; }
|
public static bool IsSubEditor() => Screen.Selected is SubEditorScreen && !Submarine.Unloading;
|
||||||
|
public static bool IsWiringMode() => Screen.Selected == GameMain.SubEditorScreen && GameMain.SubEditorScreen.WiringMode && !Submarine.Unloading;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -566,8 +566,13 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
ToolTip = toolTip
|
ToolTip = toolTip
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool isFlagsAttribute = value.GetType().IsDefined(typeof(FlagsAttribute), false);
|
||||||
|
|
||||||
foreach (object enumValue in Enum.GetValues(value.GetType()))
|
foreach (object enumValue in Enum.GetValues(value.GetType()))
|
||||||
{
|
{
|
||||||
|
if (isFlagsAttribute && !MathHelper.IsPowerOfTwo((int)enumValue)) { continue; }
|
||||||
|
|
||||||
enumDropDown.AddItem(enumValue.ToString(), enumValue);
|
enumDropDown.AddItem(enumValue.ToString(), enumValue);
|
||||||
if (((int)enumValue != 0 || (int)value == 0) && ((Enum)value).HasFlag((Enum)enumValue))
|
if (((int)enumValue != 0 || (int)value == 0) && ((Enum)value).HasFlag((Enum)enumValue))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -730,6 +730,7 @@ namespace Barotrauma.Sounds
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
playingChannels[i][j].Dispose();
|
playingChannels[i][j].Dispose();
|
||||||
|
playingChannels[i][j] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (playingChannels[i][j].FadingOutAndDisposing)
|
else if (playingChannels[i][j].FadingOutAndDisposing)
|
||||||
@@ -738,6 +739,7 @@ namespace Barotrauma.Sounds
|
|||||||
if (playingChannels[i][j].Gain <= 0.0f)
|
if (playingChannels[i][j].Gain <= 0.0f)
|
||||||
{
|
{
|
||||||
playingChannels[i][j].Dispose();
|
playingChannels[i][j].Dispose();
|
||||||
|
playingChannels[i][j] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -500,6 +500,12 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (FlowSounds.Count == 0) { return; }
|
if (FlowSounds.Count == 0) { return; }
|
||||||
|
|
||||||
|
for (int i = 0; i < targetFlowLeft.Length; i++)
|
||||||
|
{
|
||||||
|
targetFlowLeft[i] = 0.0f;
|
||||||
|
targetFlowRight[i] = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
Vector2 listenerPos = new Vector2(GameMain.SoundManager.ListenerPosition.X, GameMain.SoundManager.ListenerPosition.Y);
|
Vector2 listenerPos = new Vector2(GameMain.SoundManager.ListenerPosition.X, GameMain.SoundManager.ListenerPosition.Y);
|
||||||
foreach (Gap gap in Gap.GapList)
|
foreach (Gap gap in Gap.GapList)
|
||||||
{
|
{
|
||||||
@@ -619,7 +625,8 @@ namespace Barotrauma
|
|||||||
Vector2 soundPos = new Vector2(GameMain.SoundManager.ListenerPosition.X + (fireVolumeRight[i] - fireVolumeLeft[i]) * 100, GameMain.SoundManager.ListenerPosition.Y);
|
Vector2 soundPos = new Vector2(GameMain.SoundManager.ListenerPosition.X + (fireVolumeRight[i] - fireVolumeLeft[i]) * 100, GameMain.SoundManager.ListenerPosition.Y);
|
||||||
if (fireSoundChannels[i] == null || !fireSoundChannels[i].IsPlaying)
|
if (fireSoundChannels[i] == null || !fireSoundChannels[i].IsPlaying)
|
||||||
{
|
{
|
||||||
fireSoundChannels[i] = GetSound(fireSoundTags[i]).Play(1.0f, FlowSoundRange, soundPos);
|
fireSoundChannels[i] = GetSound(fireSoundTags[i])?.Play(1.0f, FlowSoundRange, soundPos);
|
||||||
|
if (fireSoundChannels[i] == null) { continue; }
|
||||||
fireSoundChannels[i].Looping = true;
|
fireSoundChannels[i].Looping = true;
|
||||||
}
|
}
|
||||||
fireSoundChannels[i].Gain = Math.Max(fireVolumeRight[i], fireVolumeLeft[i]);
|
fireSoundChannels[i].Gain = Math.Max(fireVolumeRight[i], fireVolumeLeft[i]);
|
||||||
@@ -954,20 +961,18 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (Level.IsLoadedOutpost && Character.Controlled.Submarine == Level.Loaded.StartOutpost)
|
if (Level.IsLoadedOutpost && Character.Controlled.Submarine == Level.Loaded.StartOutpost)
|
||||||
{
|
{
|
||||||
// Only return music type for specific outpost types to not assume that
|
// Only return music type for location types which have music tracks defined
|
||||||
// every outpost type has an associated music track (switch-case for future tracks)
|
|
||||||
var locationType = Level.Loaded.StartLocation?.Type?.Identifier?.ToLowerInvariant();
|
var locationType = Level.Loaded.StartLocation?.Type?.Identifier?.ToLowerInvariant();
|
||||||
switch (locationType)
|
if (!string.IsNullOrEmpty(locationType) && musicClips.Any(c => c.Type == locationType))
|
||||||
{
|
{
|
||||||
case "research":
|
return locationType;
|
||||||
return locationType;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Submarine targetSubmarine = Character.Controlled?.Submarine;
|
Submarine targetSubmarine = Character.Controlled?.Submarine;
|
||||||
if ((targetSubmarine != null && targetSubmarine.AtDamageDepth) ||
|
if ((targetSubmarine != null && targetSubmarine.AtDamageDepth) ||
|
||||||
(GameMain.GameScreen != null && Screen.Selected == GameMain.GameScreen && GameMain.GameScreen.Cam.Position.Y < SubmarineBody.DamageDepth))
|
(GameMain.GameScreen != null && Screen.Selected == GameMain.GameScreen && Level.Loaded != null && Level.Loaded.GetRealWorldDepth(GameMain.GameScreen.Cam.Position.Y) > Level.Loaded.RealWorldCrushDepth))
|
||||||
{
|
{
|
||||||
return "deep";
|
return "deep";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,65 +57,9 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (entity == null) { return; }
|
if (entity == null) { return; }
|
||||||
|
|
||||||
if (sounds.Count > 0 && playSound)
|
if (playSound)
|
||||||
{
|
{
|
||||||
if (soundChannel == null || !soundChannel.IsPlaying)
|
PlaySound(entity, hull, worldPosition);
|
||||||
{
|
|
||||||
if (soundSelectionMode == SoundSelectionMode.All)
|
|
||||||
{
|
|
||||||
foreach (RoundSound sound in sounds)
|
|
||||||
{
|
|
||||||
if (sound?.Sound == null)
|
|
||||||
{
|
|
||||||
string errorMsg = $"Error in StatusEffect.ApplyProjSpecific1 (sound \"{sound?.Filename ?? "unknown"}\" was null)\n" + Environment.StackTrace.CleanupStackTrace();
|
|
||||||
GameAnalyticsManager.AddErrorEventOnce("StatusEffect.ApplyProjSpecific:SoundNull1" + Environment.StackTrace.CleanupStackTrace(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
soundChannel = SoundPlayer.PlaySound(sound.Sound, worldPosition, sound.Volume, sound.Range, hullGuess: hull);
|
|
||||||
if (soundChannel != null) { soundChannel.Looping = loopSound; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int selectedSoundIndex;
|
|
||||||
if (soundSelectionMode == SoundSelectionMode.ItemSpecific && entity is Item item)
|
|
||||||
{
|
|
||||||
selectedSoundIndex = item.ID % sounds.Count;
|
|
||||||
}
|
|
||||||
else if (soundSelectionMode == SoundSelectionMode.CharacterSpecific && entity is Character user)
|
|
||||||
{
|
|
||||||
selectedSoundIndex = user.ID % sounds.Count;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
selectedSoundIndex = Rand.Int(sounds.Count);
|
|
||||||
}
|
|
||||||
var selectedSound = sounds[selectedSoundIndex];
|
|
||||||
if (selectedSound?.Sound == null)
|
|
||||||
{
|
|
||||||
string errorMsg = $"Error in StatusEffect.ApplyProjSpecific2 (sound \"{selectedSound?.Filename ?? "unknown"}\" was null)\n" + Environment.StackTrace.CleanupStackTrace();
|
|
||||||
GameAnalyticsManager.AddErrorEventOnce("StatusEffect.ApplyProjSpecific:SoundNull2" + Environment.StackTrace.CleanupStackTrace(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (selectedSound.Sound.Disposed)
|
|
||||||
{
|
|
||||||
Submarine.ReloadRoundSound(selectedSound);
|
|
||||||
}
|
|
||||||
soundChannel = SoundPlayer.PlaySound(selectedSound.Sound, worldPosition, selectedSound.Volume, selectedSound.Range, hullGuess: hull);
|
|
||||||
if (soundChannel != null) { soundChannel.Looping = loopSound; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
soundChannel.Position = new Vector3(worldPosition, 0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (soundChannel != null && soundChannel.Looping)
|
|
||||||
{
|
|
||||||
ActiveLoopingSounds.Add(this);
|
|
||||||
soundEmitter = entity;
|
|
||||||
loopStartTime = Timing.TotalTime;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (ParticleEmitter emitter in particleEmitters)
|
foreach (ParticleEmitter emitter in particleEmitters)
|
||||||
@@ -151,6 +95,69 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void PlaySound(Entity entity, Hull hull, Vector2 worldPosition)
|
||||||
|
{
|
||||||
|
if (sounds.Count == 0) return;
|
||||||
|
|
||||||
|
if (soundChannel == null || !soundChannel.IsPlaying)
|
||||||
|
{
|
||||||
|
if (soundSelectionMode == SoundSelectionMode.All)
|
||||||
|
{
|
||||||
|
foreach (RoundSound sound in sounds)
|
||||||
|
{
|
||||||
|
if (sound?.Sound == null)
|
||||||
|
{
|
||||||
|
string errorMsg = $"Error in StatusEffect.ApplyProjSpecific1 (sound \"{sound?.Filename ?? "unknown"}\" was null)\n" + Environment.StackTrace.CleanupStackTrace();
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("StatusEffect.ApplyProjSpecific:SoundNull1" + Environment.StackTrace.CleanupStackTrace(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
soundChannel = SoundPlayer.PlaySound(sound.Sound, worldPosition, sound.Volume, sound.Range, hullGuess: hull);
|
||||||
|
if (soundChannel != null) { soundChannel.Looping = loopSound; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int selectedSoundIndex;
|
||||||
|
if (soundSelectionMode == SoundSelectionMode.ItemSpecific && entity is Item item)
|
||||||
|
{
|
||||||
|
selectedSoundIndex = item.ID % sounds.Count;
|
||||||
|
}
|
||||||
|
else if (soundSelectionMode == SoundSelectionMode.CharacterSpecific && entity is Character user)
|
||||||
|
{
|
||||||
|
selectedSoundIndex = user.ID % sounds.Count;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
selectedSoundIndex = Rand.Int(sounds.Count);
|
||||||
|
}
|
||||||
|
var selectedSound = sounds[selectedSoundIndex];
|
||||||
|
if (selectedSound?.Sound == null)
|
||||||
|
{
|
||||||
|
string errorMsg = $"Error in StatusEffect.ApplyProjSpecific2 (sound \"{selectedSound?.Filename ?? "unknown"}\" was null)\n" + Environment.StackTrace.CleanupStackTrace();
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("StatusEffect.ApplyProjSpecific:SoundNull2" + Environment.StackTrace.CleanupStackTrace(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (selectedSound.Sound.Disposed)
|
||||||
|
{
|
||||||
|
Submarine.ReloadRoundSound(selectedSound);
|
||||||
|
}
|
||||||
|
soundChannel = SoundPlayer.PlaySound(selectedSound.Sound, worldPosition, selectedSound.Volume, selectedSound.Range, hullGuess: hull);
|
||||||
|
if (soundChannel != null) { soundChannel.Looping = loopSound; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
soundChannel.Position = new Vector3(worldPosition, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (soundChannel != null && soundChannel.Looping)
|
||||||
|
{
|
||||||
|
ActiveLoopingSounds.Add(this);
|
||||||
|
soundEmitter = entity;
|
||||||
|
loopStartTime = Timing.TotalTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static partial void UpdateAllProjSpecific(float deltaTime)
|
static partial void UpdateAllProjSpecific(float deltaTime)
|
||||||
{
|
{
|
||||||
bool doMuffleCheck = Timing.TotalTime > LastMuffleCheckTime + 0.2;
|
bool doMuffleCheck = Timing.TotalTime > LastMuffleCheckTime + 0.2;
|
||||||
|
|||||||
@@ -120,7 +120,8 @@ namespace Barotrauma
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="receivers">Entities that were deleted or added</param>
|
/// <param name="receivers">Entities that were deleted or added</param>
|
||||||
/// <param name="wasDeleted">Whether or not all entities are or are going to be deleted</param>
|
/// <param name="wasDeleted">Whether or not all entities are or are going to be deleted</param>
|
||||||
public AddOrDeleteCommand(List<MapEntity> receivers, bool wasDeleted)
|
/// <param name="handleInventoryBehavior">Ignore item inventories when set to false, workaround for pasting</param>
|
||||||
|
public AddOrDeleteCommand(List<MapEntity> receivers, bool wasDeleted, bool handleInventoryBehavior = true)
|
||||||
{
|
{
|
||||||
WasDeleted = wasDeleted;
|
WasDeleted = wasDeleted;
|
||||||
Receivers = receivers;
|
Receivers = receivers;
|
||||||
@@ -151,14 +152,17 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemsToDelete.Any())
|
if (itemsToDelete.Any() && handleInventoryBehavior)
|
||||||
{
|
{
|
||||||
ContainedItemsCommand.Add(new AddOrDeleteCommand(itemsToDelete, true));
|
ContainedItemsCommand.Add(new AddOrDeleteCommand(itemsToDelete, wasDeleted));
|
||||||
foreach (MapEntity item in itemsToDelete)
|
if (wasDeleted)
|
||||||
{
|
{
|
||||||
if (item != null && !item.Removed)
|
foreach (MapEntity item in itemsToDelete)
|
||||||
{
|
{
|
||||||
item.Remove();
|
if (item != null && !item.Removed)
|
||||||
|
{
|
||||||
|
item.Remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -226,10 +230,10 @@ namespace Barotrauma
|
|||||||
Debug.Assert(Receivers.All(entity => entity.GetReplacementOrThis().Removed), "Tried to redo a deletion but some items were not deleted");
|
Debug.Assert(Receivers.All(entity => entity.GetReplacementOrThis().Removed), "Tried to redo a deletion but some items were not deleted");
|
||||||
|
|
||||||
List<MapEntity> clones = MapEntity.Clone(CloneList);
|
List<MapEntity> clones = MapEntity.Clone(CloneList);
|
||||||
for (int i = 0; i < Math.Min(Receivers.Count, clones.Count); i++)
|
int length = Math.Min(Receivers.Count, clones.Count);
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
MapEntity clone = clones[i];
|
MapEntity clone = clones[i], receiver = Receivers[i];
|
||||||
MapEntity receiver = Receivers[i];
|
|
||||||
|
|
||||||
if (receiver.GetReplacementOrThis() is Item item && clone is Item cloneItem)
|
if (receiver.GetReplacementOrThis() is Item item && clone is Item cloneItem)
|
||||||
{
|
{
|
||||||
@@ -252,6 +256,11 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
receiver.GetReplacementOrThis().ReplacedBy = clone;
|
receiver.GetReplacementOrThis().ReplacedBy = clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
MapEntity clone = clones[i], receiver = Receivers[i];
|
||||||
|
|
||||||
if (clone is Item it)
|
if (clone is Item it)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,773 +0,0 @@
|
|||||||
//
|
|
||||||
// System.Web.HttpUtility
|
|
||||||
//
|
|
||||||
// Authors:
|
|
||||||
// Patrik Torstensson (Patrik.Torstensson@labs2.com)
|
|
||||||
// Wictor Wilén (decode/encode functions) (wictor@ibizkit.se)
|
|
||||||
// Tim Coleman (tim@timcoleman.com)
|
|
||||||
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
|
|
||||||
//
|
|
||||||
// Copyright (C) 2005-2010 Novell, Inc (http://www.novell.com)
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
// a copy of this software and associated documentation files (the
|
|
||||||
// "Software"), to deal in the Software without restriction, including
|
|
||||||
// without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
// permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
// the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be
|
|
||||||
// included in all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.Specialized;
|
|
||||||
using System.Globalization;
|
|
||||||
using Barotrauma.IO;
|
|
||||||
using System.Security.Permissions;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace RestSharp.Contrib
|
|
||||||
{
|
|
||||||
|
|
||||||
//#if !MONOTOUCH
|
|
||||||
// // CAS - no InheritanceDemand here as the class is sealed
|
|
||||||
// [AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
|
|
||||||
//#endif
|
|
||||||
public sealed class HttpUtility
|
|
||||||
{
|
|
||||||
sealed class HttpQSCollection : NameValueCollection
|
|
||||||
{
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
int count = Count;
|
|
||||||
if (count == 0)
|
|
||||||
return "";
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
string[] keys = AllKeys;
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
sb.AppendFormat("{0}={1}&", keys[i], this[keys[i]]);
|
|
||||||
}
|
|
||||||
if (sb.Length > 0)
|
|
||||||
sb.Length--;
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Constructors
|
|
||||||
|
|
||||||
public HttpUtility()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion // Constructors
|
|
||||||
|
|
||||||
#region Methods
|
|
||||||
|
|
||||||
/*
|
|
||||||
public static void HtmlAttributeEncode(string s, TextWriter output)
|
|
||||||
{
|
|
||||||
if (output == null)
|
|
||||||
{
|
|
||||||
#if NET_4_0
|
|
||||||
throw new ArgumentNullException ("output");
|
|
||||||
#else
|
|
||||||
throw new NullReferenceException(".NET emulation");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#if NET_4_0
|
|
||||||
HttpEncoder.Current.HtmlAttributeEncode (s, output);
|
|
||||||
#else
|
|
||||||
output.Write(HttpEncoder.HtmlAttributeEncode(s));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
public static string HtmlAttributeEncode(string s)
|
|
||||||
{
|
|
||||||
#if NET_4_0
|
|
||||||
if (s == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
using (var sw = new StringWriter ()) {
|
|
||||||
HttpEncoder.Current.HtmlAttributeEncode (s, sw);
|
|
||||||
return sw.ToString ();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
return HttpEncoder.HtmlAttributeEncode(s);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string UrlDecode(string str)
|
|
||||||
{
|
|
||||||
return UrlDecode(str, Encoding.UTF8);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char[] GetChars(System.IO.MemoryStream b, Encoding e)
|
|
||||||
{
|
|
||||||
return e.GetChars(b.GetBuffer(), 0, (int)b.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void WriteCharBytes(IList buf, char ch, Encoding e)
|
|
||||||
{
|
|
||||||
if (ch > 255)
|
|
||||||
{
|
|
||||||
foreach (byte b in e.GetBytes(new char[] { ch }))
|
|
||||||
buf.Add(b);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
buf.Add((byte)ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string UrlDecode(string s, Encoding e)
|
|
||||||
{
|
|
||||||
if (null == s)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (s.IndexOf('%') == -1 && s.IndexOf('+') == -1)
|
|
||||||
return s;
|
|
||||||
|
|
||||||
if (e == null)
|
|
||||||
e = Encoding.UTF8;
|
|
||||||
|
|
||||||
long len = s.Length;
|
|
||||||
var bytes = new List<byte>();
|
|
||||||
int xchar;
|
|
||||||
char ch;
|
|
||||||
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
ch = s[i];
|
|
||||||
if (ch == '%' && i + 2 < len && s[i + 1] != '%')
|
|
||||||
{
|
|
||||||
if (s[i + 1] == 'u' && i + 5 < len)
|
|
||||||
{
|
|
||||||
// unicode hex sequence
|
|
||||||
xchar = GetChar(s, i + 2, 4);
|
|
||||||
if (xchar != -1)
|
|
||||||
{
|
|
||||||
WriteCharBytes(bytes, (char)xchar, e);
|
|
||||||
i += 5;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
WriteCharBytes(bytes, '%', e);
|
|
||||||
}
|
|
||||||
else if ((xchar = GetChar(s, i + 1, 2)) != -1)
|
|
||||||
{
|
|
||||||
WriteCharBytes(bytes, (char)xchar, e);
|
|
||||||
i += 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WriteCharBytes(bytes, '%', e);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ch == '+')
|
|
||||||
WriteCharBytes(bytes, ' ', e);
|
|
||||||
else
|
|
||||||
WriteCharBytes(bytes, ch, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] buf = bytes.ToArray();
|
|
||||||
bytes = null;
|
|
||||||
return e.GetString(buf);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string UrlDecode(byte[] bytes, Encoding e)
|
|
||||||
{
|
|
||||||
if (bytes == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return UrlDecode(bytes, 0, bytes.Length, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int GetInt(byte b)
|
|
||||||
{
|
|
||||||
char c = (char)b;
|
|
||||||
if (c >= '0' && c <= '9')
|
|
||||||
return c - '0';
|
|
||||||
|
|
||||||
if (c >= 'a' && c <= 'f')
|
|
||||||
return c - 'a' + 10;
|
|
||||||
|
|
||||||
if (c >= 'A' && c <= 'F')
|
|
||||||
return c - 'A' + 10;
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int GetChar(byte[] bytes, int offset, int length)
|
|
||||||
{
|
|
||||||
int value = 0;
|
|
||||||
int end = length + offset;
|
|
||||||
for (int i = offset; i < end; i++)
|
|
||||||
{
|
|
||||||
int current = GetInt(bytes[i]);
|
|
||||||
if (current == -1)
|
|
||||||
return -1;
|
|
||||||
value = (value << 4) + current;
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int GetChar(string str, int offset, int length)
|
|
||||||
{
|
|
||||||
int val = 0;
|
|
||||||
int end = length + offset;
|
|
||||||
for (int i = offset; i < end; i++)
|
|
||||||
{
|
|
||||||
char c = str[i];
|
|
||||||
if (c > 127)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
int current = GetInt((byte)c);
|
|
||||||
if (current == -1)
|
|
||||||
return -1;
|
|
||||||
val = (val << 4) + current;
|
|
||||||
}
|
|
||||||
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string UrlDecode(byte[] bytes, int offset, int count, Encoding e)
|
|
||||||
{
|
|
||||||
if (bytes == null)
|
|
||||||
return null;
|
|
||||||
if (count == 0)
|
|
||||||
return String.Empty;
|
|
||||||
|
|
||||||
if (bytes == null)
|
|
||||||
throw new ArgumentNullException("bytes");
|
|
||||||
|
|
||||||
if (offset < 0 || offset > bytes.Length)
|
|
||||||
throw new ArgumentOutOfRangeException("offset");
|
|
||||||
|
|
||||||
if (count < 0 || offset + count > bytes.Length)
|
|
||||||
throw new ArgumentOutOfRangeException("count");
|
|
||||||
|
|
||||||
StringBuilder output = new StringBuilder();
|
|
||||||
System.IO.MemoryStream acc = new System.IO.MemoryStream();
|
|
||||||
|
|
||||||
int end = count + offset;
|
|
||||||
int xchar;
|
|
||||||
for (int i = offset; i < end; i++)
|
|
||||||
{
|
|
||||||
if (bytes[i] == '%' && i + 2 < count && bytes[i + 1] != '%')
|
|
||||||
{
|
|
||||||
if (bytes[i + 1] == (byte)'u' && i + 5 < end)
|
|
||||||
{
|
|
||||||
if (acc.Length > 0)
|
|
||||||
{
|
|
||||||
output.Append(GetChars(acc, e));
|
|
||||||
acc.SetLength(0);
|
|
||||||
}
|
|
||||||
xchar = GetChar(bytes, i + 2, 4);
|
|
||||||
if (xchar != -1)
|
|
||||||
{
|
|
||||||
output.Append((char)xchar);
|
|
||||||
i += 5;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ((xchar = GetChar(bytes, i + 1, 2)) != -1)
|
|
||||||
{
|
|
||||||
acc.WriteByte((byte)xchar);
|
|
||||||
i += 2;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (acc.Length > 0)
|
|
||||||
{
|
|
||||||
output.Append(GetChars(acc, e));
|
|
||||||
acc.SetLength(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bytes[i] == '+')
|
|
||||||
{
|
|
||||||
output.Append(' ');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
output.Append((char)bytes[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (acc.Length > 0)
|
|
||||||
{
|
|
||||||
output.Append(GetChars(acc, e));
|
|
||||||
}
|
|
||||||
|
|
||||||
acc = null;
|
|
||||||
return output.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] UrlDecodeToBytes(byte[] bytes)
|
|
||||||
{
|
|
||||||
if (bytes == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return UrlDecodeToBytes(bytes, 0, bytes.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] UrlDecodeToBytes(string str)
|
|
||||||
{
|
|
||||||
return UrlDecodeToBytes(str, Encoding.UTF8);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] UrlDecodeToBytes(string str, Encoding e)
|
|
||||||
{
|
|
||||||
if (str == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (e == null)
|
|
||||||
throw new ArgumentNullException("e");
|
|
||||||
|
|
||||||
return UrlDecodeToBytes(e.GetBytes(str));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] UrlDecodeToBytes(byte[] bytes, int offset, int count)
|
|
||||||
{
|
|
||||||
if (bytes == null)
|
|
||||||
return null;
|
|
||||||
if (count == 0)
|
|
||||||
return new byte[0];
|
|
||||||
|
|
||||||
int len = bytes.Length;
|
|
||||||
if (offset < 0 || offset >= len)
|
|
||||||
throw new ArgumentOutOfRangeException("offset");
|
|
||||||
|
|
||||||
if (count < 0 || offset > len - count)
|
|
||||||
throw new ArgumentOutOfRangeException("count");
|
|
||||||
|
|
||||||
System.IO.MemoryStream result = new System.IO.MemoryStream();
|
|
||||||
int end = offset + count;
|
|
||||||
for (int i = offset; i < end; i++)
|
|
||||||
{
|
|
||||||
char c = (char)bytes[i];
|
|
||||||
if (c == '+')
|
|
||||||
{
|
|
||||||
c = ' ';
|
|
||||||
}
|
|
||||||
else if (c == '%' && i < end - 2)
|
|
||||||
{
|
|
||||||
int xchar = GetChar(bytes, i + 1, 2);
|
|
||||||
if (xchar != -1)
|
|
||||||
{
|
|
||||||
c = (char)xchar;
|
|
||||||
i += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result.WriteByte((byte)c);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string UrlEncode(string str)
|
|
||||||
{
|
|
||||||
return UrlEncode(str, Encoding.UTF8);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string UrlEncode(string s, Encoding Enc)
|
|
||||||
{
|
|
||||||
if (s == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (s == String.Empty)
|
|
||||||
return String.Empty;
|
|
||||||
|
|
||||||
bool needEncode = false;
|
|
||||||
int len = s.Length;
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
char c = s[i];
|
|
||||||
if ((c < '0') || (c < 'A' && c > '9') || (c > 'Z' && c < 'a') || (c > 'z'))
|
|
||||||
{
|
|
||||||
if (HttpEncoder.NotEncoded(c))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
needEncode = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!needEncode)
|
|
||||||
return s;
|
|
||||||
|
|
||||||
// avoided GetByteCount call
|
|
||||||
byte[] bytes = new byte[Enc.GetMaxByteCount(s.Length)];
|
|
||||||
int realLen = Enc.GetBytes(s, 0, s.Length, bytes, 0);
|
|
||||||
return Encoding.ASCII.GetString(UrlEncodeToBytes(bytes, 0, realLen));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string UrlEncode(byte[] bytes)
|
|
||||||
{
|
|
||||||
if (bytes == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (bytes.Length == 0)
|
|
||||||
return String.Empty;
|
|
||||||
|
|
||||||
return Encoding.ASCII.GetString(UrlEncodeToBytes(bytes, 0, bytes.Length));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string UrlEncode(byte[] bytes, int offset, int count)
|
|
||||||
{
|
|
||||||
if (bytes == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (bytes.Length == 0)
|
|
||||||
return String.Empty;
|
|
||||||
|
|
||||||
return Encoding.ASCII.GetString(UrlEncodeToBytes(bytes, offset, count));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] UrlEncodeToBytes(string str)
|
|
||||||
{
|
|
||||||
return UrlEncodeToBytes(str, Encoding.UTF8);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] UrlEncodeToBytes(string str, Encoding e)
|
|
||||||
{
|
|
||||||
if (str == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (str.Length == 0)
|
|
||||||
return new byte[0];
|
|
||||||
|
|
||||||
byte[] bytes = e.GetBytes(str);
|
|
||||||
return UrlEncodeToBytes(bytes, 0, bytes.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] UrlEncodeToBytes(byte[] bytes)
|
|
||||||
{
|
|
||||||
if (bytes == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (bytes.Length == 0)
|
|
||||||
return new byte[0];
|
|
||||||
|
|
||||||
return UrlEncodeToBytes(bytes, 0, bytes.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] UrlEncodeToBytes(byte[] bytes, int offset, int count)
|
|
||||||
{
|
|
||||||
if (bytes == null)
|
|
||||||
return null;
|
|
||||||
#if NET_4_0
|
|
||||||
return HttpEncoder.Current.UrlEncode (bytes, offset, count);
|
|
||||||
#else
|
|
||||||
return HttpEncoder.UrlEncodeToBytes(bytes, offset, count);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string UrlEncodeUnicode(string str)
|
|
||||||
{
|
|
||||||
if (str == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return Encoding.ASCII.GetString(UrlEncodeUnicodeToBytes(str));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] UrlEncodeUnicodeToBytes(string str)
|
|
||||||
{
|
|
||||||
if (str == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (str.Length == 0)
|
|
||||||
return new byte[0];
|
|
||||||
|
|
||||||
System.IO.MemoryStream result = new System.IO.MemoryStream(str.Length);
|
|
||||||
foreach (char c in str)
|
|
||||||
{
|
|
||||||
HttpEncoder.UrlEncodeChar(c, result, true);
|
|
||||||
}
|
|
||||||
return result.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Decodes an HTML-encoded string and returns the decoded string.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="s">The HTML string to decode. </param>
|
|
||||||
/// <returns>The decoded text.</returns>
|
|
||||||
public static string HtmlDecode(string s)
|
|
||||||
{
|
|
||||||
#if NET_4_0
|
|
||||||
if (s == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
using (var sw = new StringWriter ()) {
|
|
||||||
HttpEncoder.Current.HtmlDecode (s, sw);
|
|
||||||
return sw.ToString ();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
return HttpEncoder.HtmlDecode(s);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Decodes an HTML-encoded string and sends the resulting output to a TextWriter output stream.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="s">The HTML string to decode</param>
|
|
||||||
/// <param name="output">The TextWriter output stream containing the decoded string. </param>
|
|
||||||
/*
|
|
||||||
public static void HtmlDecode(string s, TextWriter output)
|
|
||||||
{
|
|
||||||
if (output == null)
|
|
||||||
{
|
|
||||||
#if NET_4_0
|
|
||||||
throw new ArgumentNullException ("output");
|
|
||||||
#else
|
|
||||||
throw new NullReferenceException(".NET emulation");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!String.IsNullOrEmpty(s))
|
|
||||||
{
|
|
||||||
#if NET_4_0
|
|
||||||
HttpEncoder.Current.HtmlDecode (s, output);
|
|
||||||
#else
|
|
||||||
output.Write(HttpEncoder.HtmlDecode(s));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
public static string HtmlEncode(string s)
|
|
||||||
{
|
|
||||||
#if NET_4_0
|
|
||||||
if (s == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
using (var sw = new StringWriter ()) {
|
|
||||||
HttpEncoder.Current.HtmlEncode (s, sw);
|
|
||||||
return sw.ToString ();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
return HttpEncoder.HtmlEncode(s);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// HTML-encodes a string and sends the resulting output to a TextWriter output stream.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="s">The string to encode. </param>
|
|
||||||
/// <param name="output">The TextWriter output stream containing the encoded string. </param>
|
|
||||||
/*
|
|
||||||
public static void HtmlEncode(string s, TextWriter output)
|
|
||||||
{
|
|
||||||
if (output == null)
|
|
||||||
{
|
|
||||||
#if NET_4_0
|
|
||||||
throw new ArgumentNullException ("output");
|
|
||||||
#else
|
|
||||||
throw new NullReferenceException(".NET emulation");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!String.IsNullOrEmpty(s))
|
|
||||||
{
|
|
||||||
#if NET_4_0
|
|
||||||
HttpEncoder.Current.HtmlEncode (s, output);
|
|
||||||
#else
|
|
||||||
output.Write(HttpEncoder.HtmlEncode(s));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if NET_4_0
|
|
||||||
public static string HtmlEncode (object value)
|
|
||||||
{
|
|
||||||
if (value == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
IHtmlString htmlString = value as IHtmlString;
|
|
||||||
if (htmlString != null)
|
|
||||||
return htmlString.ToHtmlString ();
|
|
||||||
|
|
||||||
return HtmlEncode (value.ToString ());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string JavaScriptStringEncode (string value)
|
|
||||||
{
|
|
||||||
return JavaScriptStringEncode (value, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string JavaScriptStringEncode (string value, bool addDoubleQuotes)
|
|
||||||
{
|
|
||||||
if (String.IsNullOrEmpty (value))
|
|
||||||
return addDoubleQuotes ? "\"\"" : String.Empty;
|
|
||||||
|
|
||||||
int len = value.Length;
|
|
||||||
bool needEncode = false;
|
|
||||||
char c;
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
c = value [i];
|
|
||||||
|
|
||||||
if (c >= 0 && c <= 31 || c == 34 || c == 39 || c == 60 || c == 62 || c == 92) {
|
|
||||||
needEncode = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!needEncode)
|
|
||||||
return addDoubleQuotes ? "\"" + value + "\"" : value;
|
|
||||||
|
|
||||||
var sb = new StringBuilder ();
|
|
||||||
if (addDoubleQuotes)
|
|
||||||
sb.Append ('"');
|
|
||||||
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
c = value [i];
|
|
||||||
if (c >= 0 && c <= 7 || c == 11 || c >= 14 && c <= 31 || c == 39 || c == 60 || c == 62)
|
|
||||||
sb.AppendFormat ("\\u{0:x4}", (int)c);
|
|
||||||
else switch ((int)c) {
|
|
||||||
case 8:
|
|
||||||
sb.Append ("\\b");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 9:
|
|
||||||
sb.Append ("\\t");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 10:
|
|
||||||
sb.Append ("\\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 12:
|
|
||||||
sb.Append ("\\f");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 13:
|
|
||||||
sb.Append ("\\r");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 34:
|
|
||||||
sb.Append ("\\\"");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 92:
|
|
||||||
sb.Append ("\\\\");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
sb.Append (c);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addDoubleQuotes)
|
|
||||||
sb.Append ('"');
|
|
||||||
|
|
||||||
return sb.ToString ();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
public static string UrlPathEncode(string s)
|
|
||||||
{
|
|
||||||
#if NET_4_0
|
|
||||||
return HttpEncoder.Current.UrlPathEncode (s);
|
|
||||||
#else
|
|
||||||
return HttpEncoder.UrlPathEncode(s);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
public static NameValueCollection ParseQueryString(string query)
|
|
||||||
{
|
|
||||||
return ParseQueryString(query, Encoding.UTF8);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static NameValueCollection ParseQueryString(string query, Encoding encoding)
|
|
||||||
{
|
|
||||||
if (query == null)
|
|
||||||
throw new ArgumentNullException("query");
|
|
||||||
if (encoding == null)
|
|
||||||
throw new ArgumentNullException("encoding");
|
|
||||||
if (query.Length == 0 || (query.Length == 1 && query[0] == '?'))
|
|
||||||
return new NameValueCollection();
|
|
||||||
if (query[0] == '?')
|
|
||||||
query = query.Substring(1);
|
|
||||||
|
|
||||||
NameValueCollection result = new HttpQSCollection();
|
|
||||||
ParseQueryString(query, encoding, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void ParseQueryString(string query, Encoding encoding, NameValueCollection result)
|
|
||||||
{
|
|
||||||
if (query.Length == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
string decoded = HtmlDecode(query);
|
|
||||||
int decodedLength = decoded.Length;
|
|
||||||
int namePos = 0;
|
|
||||||
bool first = true;
|
|
||||||
while (namePos <= decodedLength)
|
|
||||||
{
|
|
||||||
int valuePos = -1, valueEnd = -1;
|
|
||||||
for (int q = namePos; q < decodedLength; q++)
|
|
||||||
{
|
|
||||||
if (valuePos == -1 && decoded[q] == '=')
|
|
||||||
{
|
|
||||||
valuePos = q + 1;
|
|
||||||
}
|
|
||||||
else if (decoded[q] == '&')
|
|
||||||
{
|
|
||||||
valueEnd = q;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (first)
|
|
||||||
{
|
|
||||||
first = false;
|
|
||||||
if (decoded[namePos] == '?')
|
|
||||||
namePos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
string name, value;
|
|
||||||
if (valuePos == -1)
|
|
||||||
{
|
|
||||||
name = null;
|
|
||||||
valuePos = namePos;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
name = UrlDecode(decoded.Substring(namePos, valuePos - namePos - 1), encoding);
|
|
||||||
}
|
|
||||||
if (valueEnd < 0)
|
|
||||||
{
|
|
||||||
namePos = -1;
|
|
||||||
valueEnd = decoded.Length;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
namePos = valueEnd + 1;
|
|
||||||
}
|
|
||||||
value = UrlDecode(decoded.Substring(valuePos, valueEnd - valuePos), encoding);
|
|
||||||
|
|
||||||
result.Add(name, value);
|
|
||||||
if (namePos == -1)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion // Methods
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -150,7 +150,7 @@ namespace Barotrauma
|
|||||||
return Color.Black;
|
return Color.Black;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t <= 0.0f) { return gradient[0]; }
|
if (t <= 0.0f || !MathUtils.IsValid(t)) { return gradient[0]; }
|
||||||
if (t >= 1.0f) { return gradient[gradient.Length - 1]; }
|
if (t >= 1.0f) { return gradient[gradient.Length - 1]; }
|
||||||
|
|
||||||
float scaledT = t * (gradient.Length - 1);
|
float scaledT = t * (gradient.Length - 1);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<RootNamespace>Barotrauma</RootNamespace>
|
<RootNamespace>Barotrauma</RootNamespace>
|
||||||
<Authors>FakeFish, Undertow Games</Authors>
|
<Authors>FakeFish, Undertow Games</Authors>
|
||||||
<Product>Barotrauma</Product>
|
<Product>Barotrauma</Product>
|
||||||
<Version>0.10.6.0</Version>
|
<Version>0.1100.0.4</Version>
|
||||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||||
<Platforms>AnyCPU;x64</Platforms>
|
<Platforms>AnyCPU;x64</Platforms>
|
||||||
<AssemblyName>Barotrauma</AssemblyName>
|
<AssemblyName>Barotrauma</AssemblyName>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<RootNamespace>Barotrauma</RootNamespace>
|
<RootNamespace>Barotrauma</RootNamespace>
|
||||||
<Authors>FakeFish, Undertow Games</Authors>
|
<Authors>FakeFish, Undertow Games</Authors>
|
||||||
<Product>Barotrauma</Product>
|
<Product>Barotrauma</Product>
|
||||||
<Version>0.10.6.0</Version>
|
<Version>0.1100.0.4</Version>
|
||||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||||
<Platforms>AnyCPU;x64</Platforms>
|
<Platforms>AnyCPU;x64</Platforms>
|
||||||
<AssemblyName>Barotrauma</AssemblyName>
|
<AssemblyName>Barotrauma</AssemblyName>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<RootNamespace>Barotrauma</RootNamespace>
|
<RootNamespace>Barotrauma</RootNamespace>
|
||||||
<Authors>FakeFish, Undertow Games</Authors>
|
<Authors>FakeFish, Undertow Games</Authors>
|
||||||
<Product>Barotrauma</Product>
|
<Product>Barotrauma</Product>
|
||||||
<Version>0.10.6.0</Version>
|
<Version>0.1100.0.4</Version>
|
||||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||||
<Platforms>AnyCPU;x64</Platforms>
|
<Platforms>AnyCPU;x64</Platforms>
|
||||||
<AssemblyName>Barotrauma</AssemblyName>
|
<AssemblyName>Barotrauma</AssemblyName>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<RootNamespace>Barotrauma</RootNamespace>
|
<RootNamespace>Barotrauma</RootNamespace>
|
||||||
<Authors>FakeFish, Undertow Games</Authors>
|
<Authors>FakeFish, Undertow Games</Authors>
|
||||||
<Product>Barotrauma Dedicated Server</Product>
|
<Product>Barotrauma Dedicated Server</Product>
|
||||||
<Version>0.10.6.0</Version>
|
<Version>0.1100.0.4</Version>
|
||||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||||
<Platforms>AnyCPU;x64</Platforms>
|
<Platforms>AnyCPU;x64</Platforms>
|
||||||
<AssemblyName>DedicatedServer</AssemblyName>
|
<AssemblyName>DedicatedServer</AssemblyName>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<RootNamespace>Barotrauma</RootNamespace>
|
<RootNamespace>Barotrauma</RootNamespace>
|
||||||
<Authors>FakeFish, Undertow Games</Authors>
|
<Authors>FakeFish, Undertow Games</Authors>
|
||||||
<Product>Barotrauma Dedicated Server</Product>
|
<Product>Barotrauma Dedicated Server</Product>
|
||||||
<Version>0.10.6.0</Version>
|
<Version>0.1100.0.4</Version>
|
||||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||||
<Platforms>AnyCPU;x64</Platforms>
|
<Platforms>AnyCPU;x64</Platforms>
|
||||||
<AssemblyName>DedicatedServer</AssemblyName>
|
<AssemblyName>DedicatedServer</AssemblyName>
|
||||||
|
|||||||
@@ -420,6 +420,7 @@ namespace Barotrauma
|
|||||||
if (writeStatus)
|
if (writeStatus)
|
||||||
{
|
{
|
||||||
WriteStatus(tempBuffer);
|
WriteStatus(tempBuffer);
|
||||||
|
(AIController as EnemyAIController)?.PetBehavior?.ServerWrite(tempBuffer);
|
||||||
HealthUpdatePending = false;
|
HealthUpdatePending = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2155,6 +2155,43 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
commands.Add(new Command("readycheck", "Commence a ready check.", (string[] args) =>
|
||||||
|
{
|
||||||
|
if (Screen.Selected == GameMain.GameScreen && GameMain.NetworkMember != null)
|
||||||
|
{
|
||||||
|
CrewManager crewManager = GameMain.GameSession?.CrewManager;
|
||||||
|
if (crewManager != null && crewManager.ActiveReadyCheck == null)
|
||||||
|
{
|
||||||
|
ReadyCheck.StartReadyCheck("");
|
||||||
|
NewMessage("Attempted to commence a ready check.", Color.Green);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NewMessage("A ready check is already running.", Color.Red);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NewMessage("Ready checks cannot be commenced in the lobby.", Color.Red);
|
||||||
|
}));
|
||||||
|
|
||||||
|
AssignOnClientRequestExecute(
|
||||||
|
"readycheck",
|
||||||
|
(senderClient, cursorWorldPos, args) =>
|
||||||
|
{
|
||||||
|
if (Screen.Selected == GameMain.GameScreen && GameMain.NetworkMember != null && !(GameMain.GameSession?.GameMode?.IsSinglePlayer ?? true))
|
||||||
|
{
|
||||||
|
CrewManager crewManager = GameMain.GameSession?.CrewManager;
|
||||||
|
if (crewManager != null && crewManager.ActiveReadyCheck == null)
|
||||||
|
{
|
||||||
|
ReadyCheck.StartReadyCheck(senderClient.Name, senderClient);
|
||||||
|
GameMain.Server.SendConsoleMessage("Attempted to commence a ready check.", senderClient);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GameMain.Server.SendConsoleMessage("A ready check is already running.", senderClient);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GameMain.Server.SendConsoleMessage("Ready checks cannot be commenced in the lobby.", senderClient);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
commands.Add(new Command("spamevents", "A debug command that creates a ton of entity events.", (string[] args) =>
|
commands.Add(new Command("spamevents", "A debug command that creates a ton of entity events.", (string[] args) =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using Barotrauma.Networking;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
partial class BeaconMission : Mission
|
||||||
|
{
|
||||||
|
public override void ServerWriteInitial(IWriteMessage msg, Client c)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ namespace Barotrauma
|
|||||||
foreach (Item item in items)
|
foreach (Item item in items)
|
||||||
{
|
{
|
||||||
item.WriteSpawnData(msg,
|
item.WriteSpawnData(msg,
|
||||||
item.OriginalID,
|
item.ID,
|
||||||
parentInventoryIDs.ContainsKey(item) ? parentInventoryIDs[item] : Entity.NullEntityID,
|
parentInventoryIDs.ContainsKey(item) ? parentInventoryIDs[item] : Entity.NullEntityID,
|
||||||
parentItemContainerIndices.ContainsKey(item) ? parentItemContainerIndices[item] : (byte)0);
|
parentItemContainerIndices.ContainsKey(item) ? parentItemContainerIndices[item] : (byte)0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
using Barotrauma.Networking;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
partial class MineralMission : Mission
|
||||||
|
{
|
||||||
|
public override void ServerWriteInitial(IWriteMessage msg, Client c)
|
||||||
|
{
|
||||||
|
foreach (var kvp in SpawnedResources)
|
||||||
|
{
|
||||||
|
msg.Write((byte)kvp.Value.Count);
|
||||||
|
var rotation = ResourceClusters[kvp.Key].Second;
|
||||||
|
msg.Write(rotation);
|
||||||
|
foreach (var r in kvp.Value)
|
||||||
|
{
|
||||||
|
r.WriteSpawnData(msg, r.ID, Entity.NullEntityID, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var kvp in RelevantLevelResources)
|
||||||
|
{
|
||||||
|
msg.Write(kvp.Key);
|
||||||
|
msg.Write((byte)kvp.Value.Length);
|
||||||
|
foreach (var i in kvp.Value)
|
||||||
|
{
|
||||||
|
msg.Write(i.ID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ namespace Barotrauma
|
|||||||
msg.Write((byte)monsters.Count);
|
msg.Write((byte)monsters.Count);
|
||||||
foreach (Character monster in monsters)
|
foreach (Character monster in monsters)
|
||||||
{
|
{
|
||||||
monster.WriteSpawnData(msg, monster.OriginalID, restrictMessageSize: false);
|
monster.WriteSpawnData(msg, monster.ID, restrictMessageSize: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using Barotrauma.Networking;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
partial class NestMission : Mission
|
||||||
|
{
|
||||||
|
public override void ServerWriteInitial(IWriteMessage msg, Client c)
|
||||||
|
{
|
||||||
|
msg.Write(nestPosition.X);
|
||||||
|
msg.Write(nestPosition.Y);
|
||||||
|
msg.Write((ushort)items.Count);
|
||||||
|
foreach (Item item in items)
|
||||||
|
{
|
||||||
|
item.WriteSpawnData(msg, item.ID, Entity.NullEntityID, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user