Unstable 0.1500.0.0
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
using Barotrauma.Sounds;
|
using Barotrauma.Particles;
|
||||||
using Barotrauma.Particles;
|
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ namespace Barotrauma
|
|||||||
public static bool DebugDrawInteract;
|
public static bool DebugDrawInteract;
|
||||||
|
|
||||||
protected float soundTimer;
|
protected float soundTimer;
|
||||||
protected float soundInterval;
|
|
||||||
protected float hudInfoTimer = 1.0f;
|
protected float hudInfoTimer = 1.0f;
|
||||||
protected bool hudInfoVisible = false;
|
protected bool hudInfoVisible = false;
|
||||||
|
|
||||||
@@ -130,7 +129,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsMouseOnUI => GUI.MouseOn != null ||
|
public static bool IsMouseOnUI => GUI.MouseOn != null ||
|
||||||
(CharacterInventory.IsMouseOnInventory() && !CharacterInventory.DraggingItemToWorld);
|
(CharacterInventory.IsMouseOnInventory && !CharacterInventory.DraggingItemToWorld);
|
||||||
|
|
||||||
public class ObjectiveEntity
|
public class ObjectiveEntity
|
||||||
{
|
{
|
||||||
@@ -161,8 +160,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
partial void InitProjSpecific(XElement mainElement)
|
partial void InitProjSpecific(XElement mainElement)
|
||||||
{
|
{
|
||||||
soundInterval = mainElement.GetAttributeFloat("soundinterval", 10.0f);
|
soundTimer = Rand.Range(0.0f, Params.SoundInterval);
|
||||||
soundTimer = Rand.Range(0.0f, soundInterval);
|
|
||||||
|
|
||||||
sounds = new List<CharacterSound>();
|
sounds = new List<CharacterSound>();
|
||||||
Params.Sounds.ForEach(s => sounds.Add(new CharacterSound(s)));
|
Params.Sounds.ForEach(s => sounds.Add(new CharacterSound(s)));
|
||||||
@@ -390,12 +388,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (attackResult.Damage <= 1.0f) { return; }
|
if (attackResult.Damage <= 1.0f) { return; }
|
||||||
}
|
}
|
||||||
|
PlaySound(CharacterSound.SoundType.Damage, maxInterval: 2);
|
||||||
if (soundTimer < soundInterval * 0.5f)
|
|
||||||
{
|
|
||||||
PlaySound(CharacterSound.SoundType.Damage);
|
|
||||||
soundTimer = soundInterval;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void KillProjSpecific(CauseOfDeathType causeOfDeath, Affliction causeOfDeathAffliction, bool log)
|
partial void KillProjSpecific(CauseOfDeathType causeOfDeath, Affliction causeOfDeathAffliction, bool log)
|
||||||
@@ -470,9 +463,9 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private List<Item> debugInteractablesInRange = new List<Item>();
|
private readonly List<Item> debugInteractablesInRange = new List<Item>();
|
||||||
private List<Item> debugInteractablesAtCursor = new List<Item>();
|
private readonly List<Item> debugInteractablesAtCursor = new List<Item>();
|
||||||
private List<Pair<Item, float>> debugInteractablesNearCursor = new List<Pair<Item, float>>();
|
private readonly List<(Item item, float dist)> debugInteractablesNearCursor = new List<(Item item, float dist)>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Finds the front (lowest depth) interactable item at a position. "Interactable" in this case means that the character can "reach" the item.
|
/// Finds the front (lowest depth) interactable item at a position. "Interactable" in this case means that the character can "reach" the item.
|
||||||
@@ -568,7 +561,7 @@ namespace Barotrauma
|
|||||||
if (distanceToItem > closestItemDistance) { continue; }
|
if (distanceToItem > closestItemDistance) { continue; }
|
||||||
if (!CanInteractWith(item)) { continue; }
|
if (!CanInteractWith(item)) { continue; }
|
||||||
|
|
||||||
debugInteractablesNearCursor.Add(new Pair<Item, float>(item, 1.0f - distanceToItem / (100.0f * aimAssistModifier)));
|
debugInteractablesNearCursor.Add((item, 1.0f - distanceToItem / (100.0f * aimAssistModifier)));
|
||||||
closestItem = item;
|
closestItem = item;
|
||||||
closestItemDistance = distanceToItem;
|
closestItemDistance = distanceToItem;
|
||||||
}
|
}
|
||||||
@@ -579,31 +572,20 @@ namespace Barotrauma
|
|||||||
private Character FindCharacterAtPosition(Vector2 mouseSimPos, float maxDist = 150.0f)
|
private Character FindCharacterAtPosition(Vector2 mouseSimPos, float maxDist = 150.0f)
|
||||||
{
|
{
|
||||||
Character closestCharacter = null;
|
Character closestCharacter = null;
|
||||||
float closestDist = 0.0f;
|
|
||||||
|
|
||||||
maxDist = ConvertUnits.ToSimUnits(maxDist);
|
maxDist = ConvertUnits.ToSimUnits(maxDist);
|
||||||
|
float closestDist = maxDist * maxDist;
|
||||||
foreach (Character c in CharacterList)
|
foreach (Character c in CharacterList)
|
||||||
{
|
{
|
||||||
if (!CanInteractWith(c, checkVisibility: false) || (c.AnimController?.SimplePhysicsEnabled ?? true)) { continue; }
|
if (!CanInteractWith(c, checkVisibility: false) || (c.AnimController?.SimplePhysicsEnabled ?? true)) { continue; }
|
||||||
|
|
||||||
float dist = Vector2.DistanceSquared(mouseSimPos, c.SimPosition);
|
float dist = Vector2.DistanceSquared(mouseSimPos, c.SimPosition);
|
||||||
if (dist < maxDist * maxDist && (closestCharacter == null || dist < closestDist))
|
if (dist < closestDist ||
|
||||||
|
(c.CampaignInteractionType != CampaignMode.InteractionType.None && closestCharacter?.CampaignInteractionType == CampaignMode.InteractionType.None && dist * 0.9f < closestDist))
|
||||||
{
|
{
|
||||||
closestCharacter = c;
|
closestCharacter = c;
|
||||||
closestDist = dist;
|
closestDist = dist;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*FarseerPhysics.Common.Transform transform;
|
|
||||||
c.AnimController.Collider.FarseerBody.GetTransform(out transform);
|
|
||||||
for (int i = 0; i < c.AnimController.Collider.FarseerBody.FixtureList.Count; i++)
|
|
||||||
{
|
|
||||||
if (c.AnimController.Collider.FarseerBody.FixtureList[i].Shape.TestPoint(ref transform, ref mouseSimPos))
|
|
||||||
{
|
|
||||||
Console.WriteLine("Hit: " + i);
|
|
||||||
closestCharacter = c;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return closestCharacter;
|
return closestCharacter;
|
||||||
@@ -638,7 +620,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (!enabled) { return; }
|
if (!enabled) { return; }
|
||||||
|
|
||||||
if (!IsDead && !IsIncapacitated)
|
if (!IsIncapacitated)
|
||||||
{
|
{
|
||||||
if (soundTimer > 0)
|
if (soundTimer > 0)
|
||||||
{
|
{
|
||||||
@@ -649,7 +631,14 @@ namespace Barotrauma
|
|||||||
switch (enemyAI.State)
|
switch (enemyAI.State)
|
||||||
{
|
{
|
||||||
case AIState.Attack:
|
case AIState.Attack:
|
||||||
PlaySound(CharacterSound.SoundType.Attack);
|
if (Rand.Value() > 0.5f)
|
||||||
|
{
|
||||||
|
PlaySound(CharacterSound.SoundType.Attack);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PlaySound(CharacterSound.SoundType.Idle);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
var petBehavior = enemyAI.PetBehavior;
|
var petBehavior = enemyAI.PetBehavior;
|
||||||
@@ -660,7 +649,6 @@ namespace Barotrauma
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
PlaySound(CharacterSound.SoundType.Idle);
|
PlaySound(CharacterSound.SoundType.Idle);
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -827,12 +815,12 @@ namespace Barotrauma
|
|||||||
GUI.DrawLine(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y),
|
GUI.DrawLine(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y),
|
||||||
new Vector2(item.DrawPosition.X, -item.DrawPosition.Y), Color.White * 0.1f, width: 4);
|
new Vector2(item.DrawPosition.X, -item.DrawPosition.Y), Color.White * 0.1f, width: 4);
|
||||||
}
|
}
|
||||||
foreach (Pair<Item, float> item in debugInteractablesNearCursor)
|
foreach ((Item item, float dist) in debugInteractablesNearCursor)
|
||||||
{
|
{
|
||||||
GUI.DrawLine(spriteBatch,
|
GUI.DrawLine(spriteBatch,
|
||||||
cursorPos,
|
cursorPos,
|
||||||
new Vector2(item.First.DrawPosition.X, -item.First.DrawPosition.Y),
|
new Vector2(item.DrawPosition.X, -item.DrawPosition.Y),
|
||||||
ToolBox.GradientLerp(item.Second, GUI.Style.Red, GUI.Style.Orange, GUI.Style.Green), width: 2);
|
ToolBox.GradientLerp(dist, GUI.Style.Red, GUI.Style.Orange, GUI.Style.Green), width: 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -856,6 +844,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
Vector2 nameSize = GUI.Font.MeasureString(name);
|
Vector2 nameSize = GUI.Font.MeasureString(name);
|
||||||
Vector2 namePos = new Vector2(pos.X, pos.Y - 10.0f - (5.0f / cam.Zoom)) - nameSize * 0.5f / cam.Zoom;
|
Vector2 namePos = new Vector2(pos.X, pos.Y - 10.0f - (5.0f / cam.Zoom)) - nameSize * 0.5f / cam.Zoom;
|
||||||
|
Color nameColor = GetNameColor();
|
||||||
|
|
||||||
Vector2 screenSize = new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
Vector2 screenSize = new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||||
Vector2 viewportSize = new Vector2(cam.WorldView.Width, cam.WorldView.Height);
|
Vector2 viewportSize = new Vector2(cam.WorldView.Width, cam.WorldView.Height);
|
||||||
@@ -865,18 +854,6 @@ namespace Barotrauma
|
|||||||
namePos *= viewportSize / screenSize;
|
namePos *= viewportSize / screenSize;
|
||||||
namePos.X += cam.WorldView.X; namePos.Y -= cam.WorldView.Y;
|
namePos.X += cam.WorldView.X; namePos.Y -= cam.WorldView.Y;
|
||||||
|
|
||||||
Color nameColor = Color.White;
|
|
||||||
if (Controlled != null && TeamID != Controlled.TeamID)
|
|
||||||
{
|
|
||||||
if (TeamID == CharacterTeamType.FriendlyNPC)
|
|
||||||
{
|
|
||||||
nameColor = UniqueNameColor ?? Color.SkyBlue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nameColor = GUI.Style.Red;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (CampaignInteractionType != CampaignMode.InteractionType.None && AllowCustomInteract)
|
if (CampaignInteractionType != CampaignMode.InteractionType.None && AllowCustomInteract)
|
||||||
{
|
{
|
||||||
var iconStyle = GUI.Style.GetComponentStyle("CampaignInteractionBubble." + CampaignInteractionType);
|
var iconStyle = GUI.Style.GetComponentStyle("CampaignInteractionBubble." + CampaignInteractionType);
|
||||||
@@ -931,6 +908,40 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Color GetNameColor()
|
||||||
|
{
|
||||||
|
CharacterTeamType team = teamID;
|
||||||
|
if (Info?.IsDisguisedAsAnother != null)
|
||||||
|
{
|
||||||
|
var idCard = Inventory.GetItemInLimbSlot(InvSlotType.Card)?.GetComponent<IdCard>();
|
||||||
|
if (idCard != null)
|
||||||
|
{
|
||||||
|
if (team == CharacterTeamType.Team2 && idCard.TeamID != CharacterTeamType.Team2)
|
||||||
|
{
|
||||||
|
team = CharacterTeamType.Team1;
|
||||||
|
}
|
||||||
|
else if (team == CharacterTeamType.Team1 && idCard.TeamID == CharacterTeamType.Team2)
|
||||||
|
{
|
||||||
|
team = CharacterTeamType.Team2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Color nameColor = GUI.Style.TextColor;
|
||||||
|
if (Controlled != null && team != Controlled.TeamID)
|
||||||
|
{
|
||||||
|
if (TeamID == CharacterTeamType.FriendlyNPC)
|
||||||
|
{
|
||||||
|
nameColor = UniqueNameColor ?? Color.SkyBlue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nameColor = GUI.Style.Red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nameColor;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a progress bar that's "linked" to the specified object (or updates an existing one if there's one already linked to the object)
|
/// Creates a progress bar that's "linked" to the specified object (or updates an existing one if there's one already linked to the object)
|
||||||
/// The progress bar will automatically fade out after 1 sec if the method hasn't been called during that time
|
/// The progress bar will automatically fade out after 1 sec if the method hasn't been called during that time
|
||||||
@@ -958,12 +969,13 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private readonly List<CharacterSound> matchingSounds = new List<CharacterSound>();
|
private readonly List<CharacterSound> matchingSounds = new List<CharacterSound>();
|
||||||
private SoundChannel soundChannel;
|
private SoundChannel soundChannel;
|
||||||
public void PlaySound(CharacterSound.SoundType soundType, float soundIntervalFactor = 1.0f)
|
public void PlaySound(CharacterSound.SoundType soundType, float soundIntervalFactor = 1.0f, float maxInterval = 0)
|
||||||
{
|
{
|
||||||
if (sounds == null || sounds.Count == 0) { return; }
|
if (sounds == null || sounds.Count == 0) { return; }
|
||||||
if (soundChannel != null && soundChannel.IsPlaying) { return; }
|
if (soundChannel != null && soundChannel.IsPlaying) { return; }
|
||||||
if (GameMain.SoundManager?.Disabled ?? true) { return; }
|
if (GameMain.SoundManager?.Disabled ?? true) { return; }
|
||||||
if (soundTimer > soundInterval * soundIntervalFactor) { return; }
|
if (soundTimer > Params.SoundInterval * soundIntervalFactor) { return; }
|
||||||
|
if (Params.SoundInterval - soundTimer < maxInterval) { return; }
|
||||||
matchingSounds.Clear();
|
matchingSounds.Clear();
|
||||||
foreach (var s in sounds)
|
foreach (var s in sounds)
|
||||||
{
|
{
|
||||||
@@ -975,7 +987,7 @@ namespace Barotrauma
|
|||||||
var selectedSound = matchingSounds.GetRandom();
|
var selectedSound = matchingSounds.GetRandom();
|
||||||
if (selectedSound?.Sound == null) { return; }
|
if (selectedSound?.Sound == null) { return; }
|
||||||
soundChannel = SoundPlayer.PlaySound(selectedSound.Sound, AnimController.WorldPosition, selectedSound.Volume, selectedSound.Range, hullGuess: CurrentHull, ignoreMuffling: selectedSound.IgnoreMuffling);
|
soundChannel = SoundPlayer.PlaySound(selectedSound.Sound, AnimController.WorldPosition, selectedSound.Volume, selectedSound.Range, hullGuess: CurrentHull, ignoreMuffling: selectedSound.IgnoreMuffling);
|
||||||
soundTimer = soundInterval;
|
soundTimer = Params.SoundInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddActiveObjectiveEntity(Entity entity, Sprite sprite, Color? color = null)
|
public void AddActiveObjectiveEntity(Entity entity, Sprite sprite, Color? color = null)
|
||||||
@@ -1028,5 +1040,20 @@ namespace Barotrauma
|
|||||||
Rand.Range(50.0f, 500.0f), null);
|
Rand.Range(50.0f, 500.0f), null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
partial void OnMoneyChanged(int prevAmount, int newAmount)
|
||||||
|
{
|
||||||
|
if (newAmount > prevAmount)
|
||||||
|
{
|
||||||
|
int increase = newAmount - prevAmount;
|
||||||
|
GUI.AddMessage(
|
||||||
|
"+" + TextManager.GetWithVariable("currencyformat", "[credits]", increase.ToString()),
|
||||||
|
GUI.Style.Yellow,
|
||||||
|
Position + Vector2.UnitY * 150.0f,
|
||||||
|
Vector2.UnitY * 10.0f,
|
||||||
|
playSound: true,
|
||||||
|
subId: Submarine?.ID ?? -1);;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -391,7 +391,26 @@ namespace Barotrauma
|
|||||||
if (npc.CampaignInteractionType == CampaignMode.InteractionType.None || npc.Submarine != character.Submarine || npc.IsDead || npc.IsIncapacitated) { continue; }
|
if (npc.CampaignInteractionType == CampaignMode.InteractionType.None || npc.Submarine != character.Submarine || npc.IsDead || npc.IsIncapacitated) { continue; }
|
||||||
|
|
||||||
var iconStyle = GUI.Style.GetComponentStyle("CampaignInteractionIcon." + npc.CampaignInteractionType);
|
var iconStyle = GUI.Style.GetComponentStyle("CampaignInteractionIcon." + npc.CampaignInteractionType);
|
||||||
GUI.DrawIndicator(spriteBatch, npc.WorldPosition, cam, npc.CurrentHull == character.CurrentHull ? 500.0f : 100.0f, iconStyle.GetDefaultSprite(), iconStyle.Color);
|
Range<float> visibleRange = new Range<float>(npc.CurrentHull == Character.Controlled.CurrentHull ? 500.0f : 100.0f, float.PositiveInfinity);
|
||||||
|
if (npc.CampaignInteractionType == CampaignMode.InteractionType.Examine)
|
||||||
|
{
|
||||||
|
//TODO: we could probably do better than just hardcoding
|
||||||
|
//a check for InteractionType.Examine here.
|
||||||
|
|
||||||
|
if (Vector2.DistanceSquared(character.Position, npc.Position) > 500f * 500f) { continue; }
|
||||||
|
|
||||||
|
var body = Submarine.CheckVisibility(character.SimPosition, npc.SimPosition, ignoreLevel: true);
|
||||||
|
if (body != null && body.UserData as Character != npc) { continue; }
|
||||||
|
|
||||||
|
visibleRange = new Range<float>(-100f, 500f);
|
||||||
|
}
|
||||||
|
GUI.DrawIndicator(
|
||||||
|
spriteBatch,
|
||||||
|
npc.WorldPosition,
|
||||||
|
cam,
|
||||||
|
visibleRange,
|
||||||
|
iconStyle.GetDefaultSprite(),
|
||||||
|
iconStyle.Color);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Item item in Item.ItemList)
|
foreach (Item item in Item.ItemList)
|
||||||
@@ -400,7 +419,7 @@ namespace Barotrauma
|
|||||||
if (Vector2.DistanceSquared(character.Position, item.Position) > 500f*500f) { continue; }
|
if (Vector2.DistanceSquared(character.Position, item.Position) > 500f*500f) { continue; }
|
||||||
var body = Submarine.CheckVisibility(character.SimPosition, item.SimPosition, ignoreLevel: true);
|
var body = Submarine.CheckVisibility(character.SimPosition, item.SimPosition, ignoreLevel: true);
|
||||||
if (body != null && body.UserData as Item != item) { continue; }
|
if (body != null && body.UserData as Item != item) { continue; }
|
||||||
GUI.DrawIndicator(spriteBatch, item.WorldPosition + new Vector2(0f, item.RectHeight * 0.65f), cam, new Vector2(-100f, 500.0f), item.IconStyle.GetDefaultSprite(), item.IconStyle.Color, createOffset: false);
|
GUI.DrawIndicator(spriteBatch, item.WorldPosition + new Vector2(0f, item.RectHeight * 0.65f), cam, new Range<float>(-100f, 500.0f), item.IconStyle.GetDefaultSprite(), item.IconStyle.Color, createOffset: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -525,12 +544,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
textPos -= new Vector2(textSize.X / 2, textSize.Y);
|
textPos -= new Vector2(textSize.X / 2, textSize.Y);
|
||||||
|
|
||||||
Color nameColor = GUI.Style.TextColor;
|
Color nameColor = character.FocusedCharacter.GetNameColor();
|
||||||
if (character.TeamID != character.FocusedCharacter.TeamID)
|
|
||||||
{
|
|
||||||
nameColor = character.FocusedCharacter.TeamID == CharacterTeamType.FriendlyNPC ? Color.SkyBlue : GUI.Style.Red;
|
|
||||||
}
|
|
||||||
|
|
||||||
GUI.DrawString(spriteBatch, textPos, focusName, nameColor, Color.Black * 0.7f, 2, GUI.SubHeadingFont);
|
GUI.DrawString(spriteBatch, textPos, focusName, nameColor, Color.Black * 0.7f, 2, GUI.SubHeadingFont);
|
||||||
textPos.X += 10.0f * GUI.Scale;
|
textPos.X += 10.0f * GUI.Scale;
|
||||||
textPos.Y += GUI.SubHeadingFont.MeasureString(focusName).Y;
|
textPos.Y += GUI.SubHeadingFont.MeasureString(focusName).Y;
|
||||||
@@ -544,11 +558,14 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (character.FocusedCharacter.CanBeDragged)
|
if (character.FocusedCharacter.CanBeDragged)
|
||||||
{
|
{
|
||||||
GUI.DrawString(spriteBatch, textPos, GetCachedHudText("GrabHint", GameMain.Config.KeyBindText(InputType.Grab)),
|
string text = character.CanEat ? "EatHint" : "GrabHint";
|
||||||
|
GUI.DrawString(spriteBatch, textPos, GetCachedHudText(text, GameMain.Config.KeyBindText(InputType.Grab)),
|
||||||
GUI.Style.Green, Color.Black, 2, GUI.SmallFont);
|
GUI.Style.Green, Color.Black, 2, GUI.SmallFont);
|
||||||
textPos.Y += largeTextSize.Y;
|
textPos.Y += largeTextSize.Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!character.DisableHealthWindow &&
|
if (!character.DisableHealthWindow &&
|
||||||
|
character.IsFriendly(character.FocusedCharacter) &&
|
||||||
character.FocusedCharacter.CharacterHealth.UseHealthWindow &&
|
character.FocusedCharacter.CharacterHealth.UseHealthWindow &&
|
||||||
character.CanInteractWith(character.FocusedCharacter, 160f, false))
|
character.CanInteractWith(character.FocusedCharacter, 160f, false))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -170,15 +170,37 @@ namespace Barotrauma
|
|||||||
if (TeamID == CharacterTeamType.FriendlyNPC) { return; }
|
if (TeamID == CharacterTeamType.FriendlyNPC) { return; }
|
||||||
if (Character.Controlled != null && Character.Controlled.TeamID != TeamID) { return; }
|
if (Character.Controlled != null && Character.Controlled.TeamID != TeamID) { return; }
|
||||||
|
|
||||||
|
// if we increased by more than 1 in one increase, then display special color (for talents)
|
||||||
|
bool specialIncrease = Math.Abs(newLevel - prevLevel) >= 1.0f;
|
||||||
|
|
||||||
if ((int)newLevel > (int)prevLevel)
|
if ((int)newLevel > (int)prevLevel)
|
||||||
{
|
{
|
||||||
int increase = Math.Max((int)newLevel - (int)prevLevel, 1);
|
int increase = Math.Max((int)newLevel - (int)prevLevel, 1);
|
||||||
GUI.AddMessage(
|
GUI.AddMessage(
|
||||||
string.Format("+{0} {1}", increase, TextManager.Get("SkillName." + skillIdentifier)),
|
string.Format("+{0} {1}", increase, TextManager.Get("SkillName." + skillIdentifier)),
|
||||||
GUI.Style.Green,
|
specialIncrease ? GUI.Style.Orange : GUI.Style.Green,
|
||||||
textPopupPos,
|
textPopupPos,
|
||||||
Vector2.UnitY * 10.0f,
|
Vector2.UnitY * 10.0f,
|
||||||
playSound: false,
|
playSound: specialIncrease,
|
||||||
|
subId: Character?.Submarine?.ID ?? -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
partial void OnExperienceChanged(int prevAmount, int newAmount, Vector2 textPopupPos)
|
||||||
|
{
|
||||||
|
if (Character.Controlled != null && Character.Controlled.TeamID != TeamID) { return; }
|
||||||
|
|
||||||
|
GameSession.TabMenuInstance?.OnExperienceChanged(Character);
|
||||||
|
|
||||||
|
if (newAmount > prevAmount)
|
||||||
|
{
|
||||||
|
int increase = newAmount - prevAmount;
|
||||||
|
GUI.AddMessage(
|
||||||
|
string.Format("+{0} {1}", increase, TextManager.Get("experienceshort")),
|
||||||
|
GUI.Style.Blue,
|
||||||
|
textPopupPos,
|
||||||
|
Vector2.UnitY * 10.0f,
|
||||||
|
playSound: true,
|
||||||
subId: Character?.Submarine?.ID ?? -1);
|
subId: Character?.Submarine?.ID ?? -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -591,6 +613,17 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
ch.Job.Skills.RemoveAll(s => !skillLevels.ContainsKey(s.Identifier));
|
ch.Job.Skills.RemoveAll(s => !skillLevels.ContainsKey(s.Identifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte savedStatValueCount = inc.ReadByte();
|
||||||
|
for (int i = 0; i < savedStatValueCount; i++)
|
||||||
|
{
|
||||||
|
int statType = inc.ReadByte();
|
||||||
|
string statIdentifier = inc.ReadString();
|
||||||
|
float statValue = inc.ReadSingle();
|
||||||
|
bool removeOnDeath = inc.ReadBoolean();
|
||||||
|
ch.ChangeSavedStatValue((StatTypes)statType, statValue, statIdentifier, removeOnDeath);
|
||||||
|
}
|
||||||
|
|
||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,15 +119,23 @@ namespace Barotrauma
|
|||||||
switch ((NetEntityEvent.Type)extraData[0])
|
switch ((NetEntityEvent.Type)extraData[0])
|
||||||
{
|
{
|
||||||
case NetEntityEvent.Type.InventoryState:
|
case NetEntityEvent.Type.InventoryState:
|
||||||
msg.WriteRangedInteger(0, 0, 3);
|
msg.WriteRangedInteger(0, 0, 4);
|
||||||
Inventory.ClientWrite(msg, extraData);
|
Inventory.ClientWrite(msg, extraData);
|
||||||
break;
|
break;
|
||||||
case NetEntityEvent.Type.Treatment:
|
case NetEntityEvent.Type.Treatment:
|
||||||
msg.WriteRangedInteger(1, 0, 3);
|
msg.WriteRangedInteger(1, 0, 4);
|
||||||
msg.Write(AnimController.Anim == AnimController.Animation.CPR);
|
msg.Write(AnimController.Anim == AnimController.Animation.CPR);
|
||||||
break;
|
break;
|
||||||
case NetEntityEvent.Type.Status:
|
case NetEntityEvent.Type.Status:
|
||||||
msg.WriteRangedInteger(2, 0, 3);
|
msg.WriteRangedInteger(2, 0, 4);
|
||||||
|
break;
|
||||||
|
case NetEntityEvent.Type.UpdateTalents:
|
||||||
|
msg.WriteRangedInteger(3, 0, 4);
|
||||||
|
msg.Write((ushort)characterTalents.Count);
|
||||||
|
foreach (var unlockedTalent in characterTalents)
|
||||||
|
{
|
||||||
|
msg.Write(unlockedTalent.Prefab.UIntIdentifier);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -258,7 +266,7 @@ namespace Barotrauma
|
|||||||
if (readStatus)
|
if (readStatus)
|
||||||
{
|
{
|
||||||
ReadStatus(msg);
|
ReadStatus(msg);
|
||||||
(AIController as EnemyAIController)?.PetBehavior?.ClientRead(msg);
|
AIController?.ClientRead(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.ReadPadBits();
|
msg.ReadPadBits();
|
||||||
@@ -291,7 +299,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case ServerNetObject.ENTITY_EVENT:
|
case ServerNetObject.ENTITY_EVENT:
|
||||||
int eventType = msg.ReadRangedInteger(0, 9);
|
int eventType = msg.ReadRangedInteger(0, 12);
|
||||||
switch (eventType)
|
switch (eventType)
|
||||||
{
|
{
|
||||||
case 0: //NetEntityEvent.Type.InventoryState
|
case 0: //NetEntityEvent.Type.InventoryState
|
||||||
@@ -387,6 +395,7 @@ namespace Barotrauma
|
|||||||
if (eventType == 4)
|
if (eventType == 4)
|
||||||
{
|
{
|
||||||
SetAttackTarget(attackLimb, targetEntity, targetSimPos);
|
SetAttackTarget(attackLimb, targetEntity, targetSimPos);
|
||||||
|
PlaySound(CharacterSound.SoundType.Attack, maxInterval: 3);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -450,6 +459,23 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 10: //NetEntityEvent.Type.UpdateExperience
|
||||||
|
int experienceAmount = msg.ReadInt32();
|
||||||
|
info?.SetExperience(experienceAmount);
|
||||||
|
break;
|
||||||
|
case 11: //NetEntityEvent.Type.UpdateTalents:
|
||||||
|
ushort talentCount = msg.ReadUInt16();
|
||||||
|
for (int i = 0; i < talentCount; i++)
|
||||||
|
{
|
||||||
|
UInt32 talentIdentifier = msg.ReadUInt32();
|
||||||
|
GiveTalent(talentIdentifier);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 12: //NetEntityEvent.Type.UpdateMoney:
|
||||||
|
int moneyAmount = msg.ReadInt32();
|
||||||
|
SetMoney(moneyAmount);
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
msg.ReadPadBits();
|
msg.ReadPadBits();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -543,7 +543,7 @@ namespace Barotrauma
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var causeOfDeath = GetCauseOfDeath();
|
var causeOfDeath = GetCauseOfDeath();
|
||||||
Character.Controlled.Kill(causeOfDeath.First, causeOfDeath.Second);
|
Character.Controlled.Kill(causeOfDeath.type, causeOfDeath.affliction);
|
||||||
Character.Controlled = null;
|
Character.Controlled = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -683,19 +683,33 @@ namespace Barotrauma
|
|||||||
float particleMaxScale = emitter?.Prefab.Properties.ScaleMax ?? 1;
|
float particleMaxScale = emitter?.Prefab.Properties.ScaleMax ?? 1;
|
||||||
float severity = Math.Min(affliction.Strength / affliction.Prefab.MaxStrength * Character.Params.BleedParticleMultiplier, 1);
|
float severity = Math.Min(affliction.Strength / affliction.Prefab.MaxStrength * Character.Params.BleedParticleMultiplier, 1);
|
||||||
float bloodParticleSize = MathHelper.Lerp(particleMinScale, particleMaxScale, severity);
|
float bloodParticleSize = MathHelper.Lerp(particleMinScale, particleMaxScale, severity);
|
||||||
|
|
||||||
|
Vector2 velocity = Rand.Vector(affliction.Strength * 0.1f);
|
||||||
if (!inWater)
|
if (!inWater)
|
||||||
{
|
{
|
||||||
bloodParticleSize *= 2.0f;
|
bloodParticleSize *= 2.0f;
|
||||||
|
velocity = targetLimb.LinearVelocity * 100.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: use the blood emitter?
|
// TODO: use the blood emitter?
|
||||||
var blood = GameMain.ParticleManager.CreateParticle(
|
var blood = GameMain.ParticleManager.CreateParticle(
|
||||||
inWater ? Character.Params.BleedParticleWater : Character.Params.BleedParticleAir,
|
inWater ? Character.Params.BleedParticleWater : Character.Params.BleedParticleAir,
|
||||||
targetLimb.WorldPosition, Rand.Vector(affliction.Strength), 0.0f, Character.AnimController.CurrentHull);
|
targetLimb.WorldPosition, velocity, 0.0f, Character.AnimController.CurrentHull);
|
||||||
|
|
||||||
if (blood != null)
|
if (blood != null && !inWater)
|
||||||
{
|
{
|
||||||
blood.Size *= bloodParticleSize;
|
blood.Size *= bloodParticleSize;
|
||||||
|
if (!string.IsNullOrEmpty(Character.BloodDecalName) && Rand.Range(0.0f, 1.0f) < 0.05f)
|
||||||
|
{
|
||||||
|
blood.OnCollision += (Vector2 pos, Hull hull) =>
|
||||||
|
{
|
||||||
|
var decal = hull?.AddDecal(Character.BloodDecalName, pos, Rand.Range(1.0f, 2.0f), isNetworkEvent: true);
|
||||||
|
if (decal != null)
|
||||||
|
{
|
||||||
|
decal.FadeTimer = decal.LifeTime - decal.FadeOutTime * 2;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
bloodParticleTimer = MathHelper.Lerp(2, 0.5f, severity);
|
bloodParticleTimer = MathHelper.Lerp(2, 0.5f, severity);
|
||||||
}
|
}
|
||||||
@@ -1968,9 +1982,9 @@ namespace Barotrauma
|
|||||||
healthBarHolder.Visible = value;
|
healthBarHolder.Visible = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly List<Pair<AfflictionPrefab, float>> newAfflictions = new List<Pair<AfflictionPrefab, float>>();
|
private readonly List<(AfflictionPrefab afflictionPrefab, float strength)> newAfflictions = new List<(AfflictionPrefab afflictionPrefab, float strength)>();
|
||||||
private readonly List<Triplet<LimbHealth, AfflictionPrefab, float>> newLimbAfflictions = new List<Triplet<LimbHealth, AfflictionPrefab, float>>();
|
private readonly List<(LimbHealth limb, AfflictionPrefab afflictionPrefab, float strength)> newLimbAfflictions = new List<(LimbHealth limb, AfflictionPrefab afflictionPrefab, float strength)>();
|
||||||
private readonly List<Pair<AfflictionPrefab.PeriodicEffect, float>> newPeriodicEffects = new List<Pair<AfflictionPrefab.PeriodicEffect, float>>();
|
private readonly List<(AfflictionPrefab.PeriodicEffect effect, float timer)> newPeriodicEffects = new List<(AfflictionPrefab.PeriodicEffect effect, float timer)>();
|
||||||
|
|
||||||
public void ClientRead(IReadMessage inc)
|
public void ClientRead(IReadMessage inc)
|
||||||
{
|
{
|
||||||
@@ -1997,41 +2011,41 @@ namespace Barotrauma
|
|||||||
for (int j = 0; j < periodicAfflictionCount; j++)
|
for (int j = 0; j < periodicAfflictionCount; j++)
|
||||||
{
|
{
|
||||||
float periodicAfflictionTimer = inc.ReadRangedSingle(afflictionPrefab.PeriodicEffects[j].MinInterval, afflictionPrefab.PeriodicEffects[j].MaxInterval, 8);
|
float periodicAfflictionTimer = inc.ReadRangedSingle(afflictionPrefab.PeriodicEffects[j].MinInterval, afflictionPrefab.PeriodicEffects[j].MaxInterval, 8);
|
||||||
newPeriodicEffects.Add(new Pair<AfflictionPrefab.PeriodicEffect, float>(afflictionPrefab.PeriodicEffects[j], periodicAfflictionTimer));
|
newPeriodicEffects.Add((afflictionPrefab.PeriodicEffects[j], periodicAfflictionTimer));
|
||||||
}
|
}
|
||||||
newAfflictions.Add(new Pair<AfflictionPrefab, float>(afflictionPrefab, afflictionStrength));
|
newAfflictions.Add((afflictionPrefab, afflictionStrength));
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Affliction affliction in afflictions)
|
foreach (Affliction affliction in afflictions)
|
||||||
{
|
{
|
||||||
//deactivate afflictions that weren't included in the network message
|
//deactivate afflictions that weren't included in the network message
|
||||||
if (!newAfflictions.Any(a => a.First == affliction.Prefab))
|
if (!newAfflictions.Any(a => a.afflictionPrefab == affliction.Prefab))
|
||||||
{
|
{
|
||||||
affliction.Strength = 0.0f;
|
affliction.Strength = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Pair<AfflictionPrefab, float> newAffliction in newAfflictions)
|
foreach (var (afflictionPrefab, strength) in newAfflictions)
|
||||||
{
|
{
|
||||||
Affliction existingAffliction = afflictions.Find(a => a.Prefab == newAffliction.First);
|
Affliction existingAffliction = afflictions.Find(a => a.Prefab == afflictionPrefab);
|
||||||
if (existingAffliction == null)
|
if (existingAffliction == null)
|
||||||
{
|
{
|
||||||
existingAffliction = newAffliction.First.Instantiate(newAffliction.Second);
|
existingAffliction = afflictionPrefab.Instantiate(strength);
|
||||||
afflictions.Add(existingAffliction);
|
afflictions.Add(existingAffliction);
|
||||||
}
|
}
|
||||||
existingAffliction.SetStrength(newAffliction.Second);
|
existingAffliction.SetStrength(strength);
|
||||||
if (existingAffliction == stunAffliction)
|
if (existingAffliction == stunAffliction)
|
||||||
{
|
{
|
||||||
Character.SetStun(existingAffliction.Strength, true, true);
|
Character.SetStun(existingAffliction.Strength, true, true);
|
||||||
}
|
}
|
||||||
foreach (var periodicEffect in newPeriodicEffects)
|
foreach (var periodicEffect in newPeriodicEffects)
|
||||||
{
|
{
|
||||||
if (!existingAffliction.Prefab.PeriodicEffects.Contains(periodicEffect.First)) { continue; }
|
if (!existingAffliction.Prefab.PeriodicEffects.Contains(periodicEffect.effect)) { continue; }
|
||||||
//timer has wrapped around, apply the effect
|
//timer has wrapped around, apply the effect
|
||||||
if (periodicEffect.Second - existingAffliction.PeriodicEffectTimers[periodicEffect.First] > periodicEffect.First.MinInterval / 2)
|
if (periodicEffect.timer - existingAffliction.PeriodicEffectTimers[periodicEffect.effect] > periodicEffect.effect.MinInterval / 2)
|
||||||
{
|
{
|
||||||
existingAffliction.PeriodicEffectTimers[periodicEffect.First] = periodicEffect.Second;
|
existingAffliction.PeriodicEffectTimers[periodicEffect.effect] = periodicEffect.timer;
|
||||||
foreach (StatusEffect effect in periodicEffect.First.StatusEffects)
|
foreach (StatusEffect effect in periodicEffect.effect.StatusEffects)
|
||||||
{
|
{
|
||||||
existingAffliction.ApplyStatusEffect(ActionType.OnActive, effect, deltaTime: 1.0f, this, targetLimb: null);
|
existingAffliction.ApplyStatusEffect(ActionType.OnActive, effect, deltaTime: 1.0f, this, targetLimb: null);
|
||||||
}
|
}
|
||||||
@@ -2063,9 +2077,9 @@ namespace Barotrauma
|
|||||||
for (int j = 0; j < periodicAfflictionCount; j++)
|
for (int j = 0; j < periodicAfflictionCount; j++)
|
||||||
{
|
{
|
||||||
float periodicAfflictionTimer = inc.ReadRangedSingle(afflictionPrefab.PeriodicEffects[j].MinInterval, afflictionPrefab.PeriodicEffects[j].MaxInterval, 8);
|
float periodicAfflictionTimer = inc.ReadRangedSingle(afflictionPrefab.PeriodicEffects[j].MinInterval, afflictionPrefab.PeriodicEffects[j].MaxInterval, 8);
|
||||||
newPeriodicEffects.Add(new Pair<AfflictionPrefab.PeriodicEffect, float>(afflictionPrefab.PeriodicEffects[j], periodicAfflictionTimer));
|
newPeriodicEffects.Add((afflictionPrefab.PeriodicEffects[j], periodicAfflictionTimer));
|
||||||
}
|
}
|
||||||
newLimbAfflictions.Add(new Triplet<LimbHealth, AfflictionPrefab, float>(limbHealths[limbIndex], afflictionPrefab, afflictionStrength));
|
newLimbAfflictions.Add((limbHealths[limbIndex], afflictionPrefab, afflictionStrength));
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (LimbHealth limbHealth in limbHealths)
|
foreach (LimbHealth limbHealth in limbHealths)
|
||||||
@@ -2073,33 +2087,33 @@ namespace Barotrauma
|
|||||||
foreach (Affliction affliction in limbHealth.Afflictions)
|
foreach (Affliction affliction in limbHealth.Afflictions)
|
||||||
{
|
{
|
||||||
//deactivate afflictions that weren't included in the network message
|
//deactivate afflictions that weren't included in the network message
|
||||||
if (!newLimbAfflictions.Any(a => a.First == limbHealth && a.Second == affliction.Prefab))
|
if (!newLimbAfflictions.Any(a => a.limb == limbHealth && a.afflictionPrefab == affliction.Prefab))
|
||||||
{
|
{
|
||||||
affliction.Strength = 0.0f;
|
affliction.Strength = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Triplet<LimbHealth, AfflictionPrefab, float> newAffliction in newLimbAfflictions)
|
foreach (var (limb, afflictionPrefab, strength) in newLimbAfflictions)
|
||||||
{
|
{
|
||||||
if (newAffliction.First != limbHealth) { continue; }
|
if (limb != limbHealth) { continue; }
|
||||||
Affliction existingAffliction = limbHealth.Afflictions.Find(a => a.Prefab == newAffliction.Second);
|
Affliction existingAffliction = limbHealth.Afflictions.Find(a => a.Prefab == afflictionPrefab);
|
||||||
if (existingAffliction == null)
|
if (existingAffliction == null)
|
||||||
{
|
{
|
||||||
existingAffliction = newAffliction.Second.Instantiate(newAffliction.Third);
|
existingAffliction = afflictionPrefab.Instantiate(strength);
|
||||||
limbHealth.Afflictions.Add(existingAffliction);
|
limbHealth.Afflictions.Add(existingAffliction);
|
||||||
}
|
}
|
||||||
existingAffliction.SetStrength(newAffliction.Third);
|
existingAffliction.SetStrength(strength);
|
||||||
|
|
||||||
foreach (var periodicEffect in newPeriodicEffects)
|
foreach (var periodicEffect in newPeriodicEffects)
|
||||||
{
|
{
|
||||||
if (!existingAffliction.Prefab.PeriodicEffects.Contains(periodicEffect.First)) { continue; }
|
if (!existingAffliction.Prefab.PeriodicEffects.Contains(periodicEffect.effect)) { continue; }
|
||||||
//timer has wrapped around, apply the effect
|
//timer has wrapped around, apply the effect
|
||||||
if (periodicEffect.Second - existingAffliction.PeriodicEffectTimers[periodicEffect.First] > periodicEffect.First.MinInterval / 2)
|
if (periodicEffect.timer - existingAffliction.PeriodicEffectTimers[periodicEffect.effect] > periodicEffect.effect.MinInterval / 2)
|
||||||
{
|
{
|
||||||
existingAffliction.PeriodicEffectTimers[periodicEffect.First] = periodicEffect.Second;
|
existingAffliction.PeriodicEffectTimers[periodicEffect.effect] = periodicEffect.timer;
|
||||||
foreach (StatusEffect effect in periodicEffect.First.StatusEffects)
|
foreach (StatusEffect effect in periodicEffect.effect.StatusEffects)
|
||||||
{
|
{
|
||||||
Limb targetLimb = Character.AnimController.Limbs.FirstOrDefault(l => l.HealthIndex == limbHealths.IndexOf(newAffliction.First));
|
Limb targetLimb = Character.AnimController.Limbs.FirstOrDefault(l => l.HealthIndex == limbHealths.IndexOf(limb));
|
||||||
existingAffliction.ApplyStatusEffect(ActionType.OnActive, effect, deltaTime: 1.0f, this, targetLimb: targetLimb);
|
existingAffliction.ApplyStatusEffect(ActionType.OnActive, effect, deltaTime: 1.0f, this, targetLimb: targetLimb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -418,14 +418,14 @@ namespace Barotrauma
|
|||||||
ShowQuestionPrompt("The automatic hull generation may not work correctly if your submarine uses curved walls. Do you want to continue? Y/N",
|
ShowQuestionPrompt("The automatic hull generation may not work correctly if your submarine uses curved walls. Do you want to continue? Y/N",
|
||||||
(option2) =>
|
(option2) =>
|
||||||
{
|
{
|
||||||
if (option2.ToLower() == "y") { GameMain.SubEditorScreen.AutoHull(); }
|
if (option2.ToLowerInvariant() == "y") { GameMain.SubEditorScreen.AutoHull(); }
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ShowQuestionPrompt("The automatic hull generation may not work correctly if your submarine uses curved walls. Do you want to continue? Y/N",
|
ShowQuestionPrompt("The automatic hull generation may not work correctly if your submarine uses curved walls. Do you want to continue? Y/N",
|
||||||
(option) => { if (option.ToLower() == "y") GameMain.SubEditorScreen.AutoHull(); });
|
(option) => { if (option.ToLowerInvariant() == "y") GameMain.SubEditorScreen.AutoHull(); });
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -608,7 +608,7 @@ namespace Barotrauma
|
|||||||
ShowQuestionPrompt($"Some keybinds may render the game unusable, are you sure you want to make these keybinds persistent? ({Keybinds.Count} keybind(s) assigned) Y/N",
|
ShowQuestionPrompt($"Some keybinds may render the game unusable, are you sure you want to make these keybinds persistent? ({Keybinds.Count} keybind(s) assigned) Y/N",
|
||||||
(option2) =>
|
(option2) =>
|
||||||
{
|
{
|
||||||
if (option2.ToLower() != "y")
|
if (option2.ToLowerInvariant() != "y")
|
||||||
{
|
{
|
||||||
NewMessage("Aborted.", GUI.Style.Red);
|
NewMessage("Aborted.", GUI.Style.Red);
|
||||||
return;
|
return;
|
||||||
@@ -689,6 +689,9 @@ namespace Barotrauma
|
|||||||
AssignRelayToServer("setskill", true);
|
AssignRelayToServer("setskill", true);
|
||||||
AssignRelayToServer("readycheck", true);
|
AssignRelayToServer("readycheck", true);
|
||||||
|
|
||||||
|
AssignRelayToServer("givetalent", true);
|
||||||
|
AssignRelayToServer("giveexperience", true);
|
||||||
|
|
||||||
AssignOnExecute("control", (string[] args) =>
|
AssignOnExecute("control", (string[] args) =>
|
||||||
{
|
{
|
||||||
if (args.Length < 1) return;
|
if (args.Length < 1) return;
|
||||||
|
|||||||
@@ -163,6 +163,7 @@ namespace Barotrauma
|
|||||||
public static ScalableFont SubHeadingFont => Style?.SubHeadingFont;
|
public static ScalableFont SubHeadingFont => Style?.SubHeadingFont;
|
||||||
public static ScalableFont DigitalFont => Style?.DigitalFont;
|
public static ScalableFont DigitalFont => Style?.DigitalFont;
|
||||||
public static ScalableFont HotkeyFont => Style?.HotkeyFont;
|
public static ScalableFont HotkeyFont => Style?.HotkeyFont;
|
||||||
|
public static ScalableFont MonospacedFont => Style?.MonospacedFont;
|
||||||
|
|
||||||
public static ScalableFont CJKFont { get; private set; }
|
public static ScalableFont CJKFont { get; private set; }
|
||||||
|
|
||||||
@@ -306,7 +307,7 @@ namespace Barotrauma
|
|||||||
});
|
});
|
||||||
|
|
||||||
SubmarineIcon = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(452, 385, 182, 81), new Vector2(0.5f, 0.5f));
|
SubmarineIcon = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(452, 385, 182, 81), new Vector2(0.5f, 0.5f));
|
||||||
arrow = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(392, 393, 49, 45), new Vector2(0.5f, 0.5f));
|
arrow = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(393, 393, 49, 45), new Vector2(0.5f, 0.5f));
|
||||||
SpeechBubbleIcon = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(385, 449, 66, 60), new Vector2(0.5f, 0.5f));
|
SpeechBubbleIcon = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(385, 449, 66, 60), new Vector2(0.5f, 0.5f));
|
||||||
BrokenIcon = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(898, 386, 123, 123), new Vector2(0.5f, 0.5f));
|
BrokenIcon = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(898, 386, 123, 123), new Vector2(0.5f, 0.5f));
|
||||||
}
|
}
|
||||||
@@ -672,6 +673,12 @@ namespace Barotrauma
|
|||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: SamplerStateClamp, rasterizerState: GameMain.ScissorTestEnable);
|
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: SamplerStateClamp, rasterizerState: GameMain.ScissorTestEnable);
|
||||||
|
|
||||||
|
if (GameMain.GameSession?.CrewManager is { DraggedOrder: { SymbolSprite: { } orderSprite, Color: var color }, DragOrder: true })
|
||||||
|
{
|
||||||
|
float spriteSize = Math.Max(orderSprite.size.X, orderSprite.size.Y);
|
||||||
|
orderSprite.Draw(spriteBatch, PlayerInput.LatestMousePosition, color, orderSprite.size / 2f, scale: 32f / spriteSize * Scale);
|
||||||
|
}
|
||||||
|
|
||||||
var sprite = MouseCursorSprites[(int)MouseCursor] ?? MouseCursorSprites[(int)CursorState.Default];
|
var sprite = MouseCursorSprites[(int)MouseCursor] ?? MouseCursorSprites[(int)CursorState.Default];
|
||||||
sprite.Draw(spriteBatch, PlayerInput.LatestMousePosition, Color.White, sprite.Origin, 0f, Scale / 1.5f);
|
sprite.Draw(spriteBatch, PlayerInput.LatestMousePosition, Color.White, sprite.Origin, 0f, Scale / 1.5f);
|
||||||
|
|
||||||
@@ -928,12 +935,13 @@ namespace Barotrauma
|
|||||||
MouseOn = null;
|
MouseOn = null;
|
||||||
int inventoryIndex = -1;
|
int inventoryIndex = -1;
|
||||||
|
|
||||||
if (Inventory.IsMouseOnInventory())
|
Inventory.RefreshMouseOnInventory();
|
||||||
|
if (Inventory.IsMouseOnInventory)
|
||||||
{
|
{
|
||||||
inventoryIndex = updateList.IndexOf(CharacterHUD.HUDFrame);
|
inventoryIndex = updateList.IndexOf(CharacterHUD.HUDFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PlayerInput.PrimaryMouseButtonHeld() && !PlayerInput.PrimaryMouseButtonClicked())
|
if ((!PlayerInput.PrimaryMouseButtonHeld() && !PlayerInput.PrimaryMouseButtonClicked()) || prevMouseOn == null)
|
||||||
{
|
{
|
||||||
for (var i = updateList.Count - 1; i > inventoryIndex; i--)
|
for (var i = updateList.Count - 1; i > inventoryIndex; i--)
|
||||||
{
|
{
|
||||||
@@ -941,10 +949,9 @@ namespace Barotrauma
|
|||||||
if (!c.CanBeFocused) { continue; }
|
if (!c.CanBeFocused) { continue; }
|
||||||
if (c.MouseRect.Contains(PlayerInput.MousePosition))
|
if (c.MouseRect.Contains(PlayerInput.MousePosition))
|
||||||
{
|
{
|
||||||
if ((!PlayerInput.PrimaryMouseButtonHeld() && !PlayerInput.PrimaryMouseButtonClicked()) || c == prevMouseOn)
|
if ((!PlayerInput.PrimaryMouseButtonHeld() && !PlayerInput.PrimaryMouseButtonClicked()) || c == prevMouseOn || prevMouseOn == null)
|
||||||
{
|
{
|
||||||
MouseOn = c;
|
MouseOn = c;
|
||||||
var sakdjfnsjkd = c.MouseRect;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -958,7 +965,6 @@ namespace Barotrauma
|
|||||||
MouseCursor = UpdateMouseCursorState(MouseOn);
|
MouseCursor = UpdateMouseCursorState(MouseOn);
|
||||||
return MouseOn;
|
return MouseOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CursorState UpdateMouseCursorState(GUIComponent c)
|
private static CursorState UpdateMouseCursorState(GUIComponent c)
|
||||||
@@ -1066,7 +1072,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Inventory.IsMouseOnInventory()) { return Inventory.GetInventoryMouseCursor(); }
|
if (Inventory.IsMouseOnInventory) { return Inventory.GetInventoryMouseCursor(); }
|
||||||
|
|
||||||
var character = Character.Controlled;
|
var character = Character.Controlled;
|
||||||
// ReSharper disable once InvertIf
|
// ReSharper disable once InvertIf
|
||||||
@@ -1343,7 +1349,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
/// <param name="createOffset">Should the indicator move based on the camera position?</param>
|
/// <param name="createOffset">Should the indicator move based on the camera position?</param>
|
||||||
/// <param name="overrideAlpha">Override the distance-based alpha value with the specified alpha value</param>
|
/// <param name="overrideAlpha">Override the distance-based alpha value with the specified alpha value</param>
|
||||||
public static void DrawIndicator(SpriteBatch spriteBatch, in Vector2 worldPosition, Camera cam, in Vector2 visibleRange, Sprite sprite, in Color color,
|
public static void DrawIndicator(SpriteBatch spriteBatch, in Vector2 worldPosition, Camera cam, in Range<float> visibleRange, Sprite sprite, in Color color,
|
||||||
bool createOffset = true, float scaleMultiplier = 1.0f, float? overrideAlpha = null)
|
bool createOffset = true, float scaleMultiplier = 1.0f, float? overrideAlpha = null)
|
||||||
{
|
{
|
||||||
Vector2 diff = worldPosition - cam.WorldViewCenter;
|
Vector2 diff = worldPosition - cam.WorldViewCenter;
|
||||||
@@ -1351,9 +1357,9 @@ namespace Barotrauma
|
|||||||
|
|
||||||
float symbolScale = Math.Min(64.0f / sprite.size.X, 1.0f) * scaleMultiplier * Scale;
|
float symbolScale = Math.Min(64.0f / sprite.size.X, 1.0f) * scaleMultiplier * Scale;
|
||||||
|
|
||||||
if (overrideAlpha.HasValue || (dist > visibleRange.X && dist < visibleRange.Y))
|
if (overrideAlpha.HasValue || (dist > visibleRange.Start && dist < visibleRange.End))
|
||||||
{
|
{
|
||||||
float alpha = overrideAlpha ?? MathUtils.Min((dist - visibleRange.X) / 100.0f, 1.0f - ((dist - visibleRange.Y + 100f) / 100.0f), 1.0f);
|
float alpha = overrideAlpha ?? MathUtils.Min((dist - visibleRange.Start) / 100.0f, 1.0f - ((dist - visibleRange.End + 100f) / 100.0f), 1.0f);
|
||||||
Vector2 targetScreenPos = cam.WorldToScreen(worldPosition);
|
Vector2 targetScreenPos = cam.WorldToScreen(worldPosition);
|
||||||
|
|
||||||
if (!createOffset)
|
if (!createOffset)
|
||||||
@@ -1417,7 +1423,7 @@ namespace Barotrauma
|
|||||||
public static void DrawIndicator(SpriteBatch spriteBatch, Vector2 worldPosition, Camera cam, float hideDist, Sprite sprite, Color color,
|
public static void DrawIndicator(SpriteBatch spriteBatch, Vector2 worldPosition, Camera cam, float hideDist, Sprite sprite, Color color,
|
||||||
bool createOffset = true, float scaleMultiplier = 1.0f, float? overrideAlpha = null)
|
bool createOffset = true, float scaleMultiplier = 1.0f, float? overrideAlpha = null)
|
||||||
{
|
{
|
||||||
DrawIndicator(spriteBatch, worldPosition, cam, new Vector2(hideDist, float.PositiveInfinity), sprite, color, createOffset, scaleMultiplier, overrideAlpha);
|
DrawIndicator(spriteBatch, worldPosition, cam, new Range<float>(hideDist, float.PositiveInfinity), sprite, color, createOffset, scaleMultiplier, overrideAlpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DrawLine(SpriteBatch sb, Vector2 start, Vector2 end, Color clr, float depth = 0.0f, float width = 1)
|
public static void DrawLine(SpriteBatch sb, Vector2 start, Vector2 end, Color clr, float depth = 0.0f, float width = 1)
|
||||||
@@ -1520,6 +1526,11 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void DrawFilledRectangle(SpriteBatch sb, RectangleF rect, Color clr, float depth = 0.0f)
|
||||||
|
{
|
||||||
|
DrawFilledRectangle(sb, rect.Location, rect.Size, clr, depth);
|
||||||
|
}
|
||||||
|
|
||||||
public static void DrawFilledRectangle(SpriteBatch sb, Vector2 start, Vector2 size, Color clr, float depth = 0.0f)
|
public static void DrawFilledRectangle(SpriteBatch sb, Vector2 start, Vector2 size, Color clr, float depth = 0.0f)
|
||||||
{
|
{
|
||||||
if (size.X < 0)
|
if (size.X < 0)
|
||||||
|
|||||||
@@ -52,13 +52,13 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public GUIComponent GetChild(int index)
|
public GUIComponent GetChild(int index)
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= CountChildren) return null;
|
if (index < 0 || index >= CountChildren) { return null; }
|
||||||
return RectTransform.GetChild(index).GUIComponent;
|
return RectTransform.GetChild(index).GUIComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetChildIndex(GUIComponent child)
|
public int GetChildIndex(GUIComponent child)
|
||||||
{
|
{
|
||||||
if (child == null) return -1;
|
if (child == null) { return -1; }
|
||||||
return RectTransform.GetChildIndex(child.RectTransform);
|
return RectTransform.GetChildIndex(child.RectTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
foreach (GUIComponent child in Children)
|
foreach (GUIComponent child in Children)
|
||||||
{
|
{
|
||||||
if (child.UserData == obj || (child.userData != null && child.userData.Equals(obj))) return child;
|
if (child.UserData == obj || (child.userData != null && child.userData.Equals(obj))) { return child; }
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -175,6 +175,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public bool GlowOnSelect { get; set; }
|
public bool GlowOnSelect { get; set; }
|
||||||
|
|
||||||
|
public Vector2 UVOffset { get; set; }
|
||||||
|
|
||||||
private CoroutineHandle pulsateCoroutine;
|
private CoroutineHandle pulsateCoroutine;
|
||||||
|
|
||||||
protected Color flashColor;
|
protected Color flashColor;
|
||||||
@@ -256,9 +258,9 @@ namespace Barotrauma
|
|||||||
|
|
||||||
protected Rectangle ClampRect(Rectangle r)
|
protected Rectangle ClampRect(Rectangle r)
|
||||||
{
|
{
|
||||||
if (Parent == null || !ClampMouseRectToParent) return r;
|
if (Parent == null || !ClampMouseRectToParent) { return r; }
|
||||||
Rectangle parentRect = Parent.ClampRect(Parent.Rect);
|
Rectangle parentRect = Parent.ClampRect(Parent.Rect);
|
||||||
if (parentRect.Width <= 0 || parentRect.Height <= 0) return Rectangle.Empty;
|
if (parentRect.Width <= 0 || parentRect.Height <= 0) { return Rectangle.Empty; }
|
||||||
if (parentRect.X > r.X)
|
if (parentRect.X > r.X)
|
||||||
{
|
{
|
||||||
int diff = parentRect.X - r.X;
|
int diff = parentRect.X - r.X;
|
||||||
@@ -281,7 +283,7 @@ namespace Barotrauma
|
|||||||
int diff = (r.Y + r.Height) - (parentRect.Y + parentRect.Height);
|
int diff = (r.Y + r.Height) - (parentRect.Y + parentRect.Height);
|
||||||
r.Height -= diff;
|
r.Height -= diff;
|
||||||
}
|
}
|
||||||
if (r.Width <= 0 || r.Height <= 0) return Rectangle.Empty;
|
if (r.Width <= 0 || r.Height <= 0) { return Rectangle.Empty; }
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,7 +297,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (!CanBeFocused) return Rectangle.Empty;
|
if (!CanBeFocused) { return Rectangle.Empty; }
|
||||||
return ClampMouseRectToParent ? ClampRect(Rect) : Rect;
|
return ClampMouseRectToParent ? ClampRect(Rect) : Rect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -431,7 +433,7 @@ namespace Barotrauma
|
|||||||
#region Updating
|
#region Updating
|
||||||
public virtual void AddToGUIUpdateList(bool ignoreChildren = false, int order = 0)
|
public virtual void AddToGUIUpdateList(bool ignoreChildren = false, int order = 0)
|
||||||
{
|
{
|
||||||
if (!Visible) return;
|
if (!Visible) { return; }
|
||||||
|
|
||||||
UpdateOrder = order;
|
UpdateOrder = order;
|
||||||
GUI.AddToUpdateList(this);
|
GUI.AddToUpdateList(this);
|
||||||
@@ -463,7 +465,7 @@ namespace Barotrauma
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void UpdateManually(float deltaTime, bool alsoChildren = false, bool recursive = true)
|
public void UpdateManually(float deltaTime, bool alsoChildren = false, bool recursive = true)
|
||||||
{
|
{
|
||||||
if (!Visible) return;
|
if (!Visible) { return; }
|
||||||
|
|
||||||
AutoUpdate = false;
|
AutoUpdate = false;
|
||||||
Update(deltaTime);
|
Update(deltaTime);
|
||||||
@@ -475,7 +477,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
protected virtual void Update(float deltaTime)
|
protected virtual void Update(float deltaTime)
|
||||||
{
|
{
|
||||||
if (!Visible) return;
|
if (!Visible) { return; }
|
||||||
|
|
||||||
if (CanBeFocused && OnSecondaryClicked != null)
|
if (CanBeFocused && OnSecondaryClicked != null)
|
||||||
{
|
{
|
||||||
@@ -555,7 +557,7 @@ namespace Barotrauma
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual void DrawManually(SpriteBatch spriteBatch, bool alsoChildren = false, bool recursive = true)
|
public virtual void DrawManually(SpriteBatch spriteBatch, bool alsoChildren = false, bool recursive = true)
|
||||||
{
|
{
|
||||||
if (!Visible) return;
|
if (!Visible) { return; }
|
||||||
|
|
||||||
AutoDraw = false;
|
AutoDraw = false;
|
||||||
Draw(spriteBatch);
|
Draw(spriteBatch);
|
||||||
@@ -598,7 +600,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
protected virtual void Draw(SpriteBatch spriteBatch)
|
protected virtual void Draw(SpriteBatch spriteBatch)
|
||||||
{
|
{
|
||||||
if (!Visible) return;
|
if (!Visible) { return; }
|
||||||
var rect = Rect;
|
var rect = Rect;
|
||||||
|
|
||||||
GetBlendedColor(GetColor(State), ref _currentColor);
|
GetBlendedColor(GetColor(State), ref _currentColor);
|
||||||
@@ -653,7 +655,7 @@ namespace Barotrauma
|
|||||||
? MathUtils.InverseLerp(0, SpriteCrossFadeTime, ToolBox.GetEasing(uiSprite.TransitionMode, spriteFadeTimer)) : 0;
|
? MathUtils.InverseLerp(0, SpriteCrossFadeTime, ToolBox.GetEasing(uiSprite.TransitionMode, spriteFadeTimer)) : 0;
|
||||||
if (alphaMultiplier > 0)
|
if (alphaMultiplier > 0)
|
||||||
{
|
{
|
||||||
uiSprite.Draw(spriteBatch, rect, previousColor * alphaMultiplier, SpriteEffects);
|
uiSprite.Draw(spriteBatch, rect, previousColor * alphaMultiplier, SpriteEffects, uvOffset: UVOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -667,7 +669,11 @@ namespace Barotrauma
|
|||||||
? MathUtils.InverseLerp(SpriteCrossFadeTime, 0, ToolBox.GetEasing(uiSprite.TransitionMode, spriteFadeTimer)) : (_currentColor.A / 255.0f);
|
? MathUtils.InverseLerp(SpriteCrossFadeTime, 0, ToolBox.GetEasing(uiSprite.TransitionMode, spriteFadeTimer)) : (_currentColor.A / 255.0f);
|
||||||
if (alphaMultiplier > 0)
|
if (alphaMultiplier > 0)
|
||||||
{
|
{
|
||||||
uiSprite.Draw(spriteBatch, rect, _currentColor * alphaMultiplier, SpriteEffects);
|
// * (rect.Location.Y - PlayerInput.MousePosition.Y) / rect.Height
|
||||||
|
Vector2 offset = new Vector2(
|
||||||
|
MathUtils.PositiveModulo((int)-UVOffset.X, uiSprite.Sprite.SourceRect.Width),
|
||||||
|
MathUtils.PositiveModulo((int)-UVOffset.Y, uiSprite.Sprite.SourceRect.Height));
|
||||||
|
uiSprite.Draw(spriteBatch, rect, _currentColor * alphaMultiplier, SpriteEffects, uvOffset: offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -708,7 +714,7 @@ namespace Barotrauma
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void DrawToolTip(SpriteBatch spriteBatch)
|
public void DrawToolTip(SpriteBatch spriteBatch)
|
||||||
{
|
{
|
||||||
if (!Visible) return;
|
if (!Visible) { return; }
|
||||||
DrawToolTip(spriteBatch, ToolTip, GUI.MouseOn.Rect, TooltipRichTextData);
|
DrawToolTip(spriteBatch, ToolTip, GUI.MouseOn.Rect, TooltipRichTextData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1048,7 +1054,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
case "language":
|
case "language":
|
||||||
string[] languages = element.GetAttributeStringArray(attribute.Name.ToString(), new string[0]);
|
string[] languages = element.GetAttributeStringArray(attribute.Name.ToString(), new string[0]);
|
||||||
if (!languages.Any(l => GameMain.Config.Language.ToLower() == l.ToLower())) { return false; }
|
if (!languages.Any(l => GameMain.Config.Language.Equals(l, StringComparison.OrdinalIgnoreCase))) { return false; }
|
||||||
break;
|
break;
|
||||||
case "gameversion":
|
case "gameversion":
|
||||||
var version = new Version(attribute.Value);
|
var version = new Version(attribute.Value);
|
||||||
@@ -1213,8 +1219,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private static GUIImage LoadGUIImage(XElement element, RectTransform parent)
|
private static GUIImage LoadGUIImage(XElement element, RectTransform parent)
|
||||||
{
|
{
|
||||||
Sprite sprite = null;
|
Sprite sprite;
|
||||||
|
|
||||||
string url = element.GetAttributeString("url", "");
|
string url = element.GetAttributeString("url", "");
|
||||||
if (!string.IsNullOrEmpty(url))
|
if (!string.IsNullOrEmpty(url))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (OutlineColor != Color.Transparent)
|
if (OutlineColor != Color.Transparent)
|
||||||
{
|
{
|
||||||
GUI.DrawRectangle(spriteBatch, Rect, OutlineColor * (OutlineColor.A/255.0f), false, thickness: OutlineThickness);
|
GUI.DrawRectangle(spriteBatch, Rect, OutlineColor, false, thickness: OutlineThickness);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ namespace Barotrauma
|
|||||||
public GUIFrame Content { get; private set; }
|
public GUIFrame Content { get; private set; }
|
||||||
public GUIScrollBar ScrollBar { get; private set; }
|
public GUIScrollBar ScrollBar { get; private set; }
|
||||||
|
|
||||||
private Dictionary<GUIComponent, bool> childVisible = new Dictionary<GUIComponent, bool>();
|
private readonly Dictionary<GUIComponent, bool> childVisible = new Dictionary<GUIComponent, bool>();
|
||||||
|
|
||||||
private int totalSize;
|
private int totalSize;
|
||||||
private bool childrenNeedsRecalculation;
|
private bool childrenNeedsRecalculation;
|
||||||
@@ -224,7 +224,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (value == false && canDragElements && draggedElement != null)
|
if (value == false && canDragElements && draggedElement != null)
|
||||||
{
|
{
|
||||||
draggedElement = null;
|
DraggedElement = null;
|
||||||
}
|
}
|
||||||
canDragElements = value;
|
canDragElements = value;
|
||||||
}
|
}
|
||||||
@@ -233,8 +233,21 @@ namespace Barotrauma
|
|||||||
private GUIComponent draggedElement;
|
private GUIComponent draggedElement;
|
||||||
private Rectangle draggedReferenceRectangle;
|
private Rectangle draggedReferenceRectangle;
|
||||||
private Point draggedReferenceOffset;
|
private Point draggedReferenceOffset;
|
||||||
|
public bool HasDraggedElementIndexChanged { get; private set; }
|
||||||
|
|
||||||
public GUIComponent DraggedElement => draggedElement;
|
public GUIComponent DraggedElement
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return draggedElement;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == draggedElement) { return; }
|
||||||
|
draggedElement = value;
|
||||||
|
HasDraggedElementIndexChanged = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private readonly bool isHorizontal;
|
private readonly bool isHorizontal;
|
||||||
|
|
||||||
@@ -472,7 +485,7 @@ namespace Barotrauma
|
|||||||
if (!PlayerInput.PrimaryMouseButtonHeld())
|
if (!PlayerInput.PrimaryMouseButtonHeld())
|
||||||
{
|
{
|
||||||
OnRearranged?.Invoke(this, draggedElement.UserData);
|
OnRearranged?.Invoke(this, draggedElement.UserData);
|
||||||
draggedElement = null;
|
DraggedElement = null;
|
||||||
RepositionChildren();
|
RepositionChildren();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -518,6 +531,7 @@ namespace Barotrauma
|
|||||||
if (currIndex != index)
|
if (currIndex != index)
|
||||||
{
|
{
|
||||||
draggedElement.RectTransform.RepositionChildInHierarchy(currIndex);
|
draggedElement.RectTransform.RepositionChildInHierarchy(currIndex);
|
||||||
|
HasDraggedElementIndexChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -577,7 +591,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (CanDragElements && PlayerInput.PrimaryMouseButtonDown() && GUI.MouseOn == child)
|
if (CanDragElements && PlayerInput.PrimaryMouseButtonDown() && GUI.MouseOn == child)
|
||||||
{
|
{
|
||||||
draggedElement = child;
|
DraggedElement = child;
|
||||||
draggedReferenceRectangle = child.Rect;
|
draggedReferenceRectangle = child.Rect;
|
||||||
draggedReferenceOffset = child.RectTransform.AbsoluteOffset;
|
draggedReferenceOffset = child.RectTransform.AbsoluteOffset;
|
||||||
}
|
}
|
||||||
@@ -750,7 +764,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((GUI.IsMouseOn(this) || GUI.IsMouseOn(ScrollBar)) && AllowMouseWheelScroll && PlayerInput.ScrollWheelSpeed != 0)
|
if (PlayerInput.ScrollWheelSpeed != 0 && AllowMouseWheelScroll && (FindScrollableParentListBox(GUI.MouseOn) == this || GUI.IsMouseOn(ScrollBar)))
|
||||||
{
|
{
|
||||||
if (SmoothScroll)
|
if (SmoothScroll)
|
||||||
{
|
{
|
||||||
@@ -774,7 +788,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ScrollBar.Enabled = ScrollBarEnabled && BarSize < 1.0f;
|
ScrollBar.Enabled = ScrollBarEnabled && BarSize < 1.0f;
|
||||||
if (AutoHideScrollBar)
|
if (AutoHideScrollBar)
|
||||||
{
|
{
|
||||||
@@ -786,6 +799,13 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static GUIListBox FindScrollableParentListBox(GUIComponent target)
|
||||||
|
{
|
||||||
|
if (target is GUIListBox listBox && listBox.ScrollBarEnabled && listBox.BarSize < 1.0f) { return listBox; }
|
||||||
|
if (target?.Parent == null) { return null; }
|
||||||
|
return FindScrollableParentListBox(target.Parent);
|
||||||
|
}
|
||||||
|
|
||||||
public void SelectNext(bool force = false, bool autoScroll = true, bool takeKeyBoardFocus = false)
|
public void SelectNext(bool force = false, bool autoScroll = true, bool takeKeyBoardFocus = false)
|
||||||
{
|
{
|
||||||
int index = SelectedIndex + 1;
|
int index = SelectedIndex + 1;
|
||||||
@@ -982,7 +1002,7 @@ namespace Barotrauma
|
|||||||
if (child == null) { return; }
|
if (child == null) { return; }
|
||||||
child.RectTransform.Parent = null;
|
child.RectTransform.Parent = null;
|
||||||
if (selected.Contains(child)) { selected.Remove(child); }
|
if (selected.Contains(child)) { selected.Remove(child); }
|
||||||
if (draggedElement == child) { draggedElement = null; }
|
if (draggedElement == child) { DraggedElement = null; }
|
||||||
UpdateScrollBarSize();
|
UpdateScrollBarSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,87 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
public class GUIScissorComponent: GUIComponent
|
||||||
|
{
|
||||||
|
public GUIComponent Content;
|
||||||
|
|
||||||
|
public GUIScissorComponent(RectTransform rectT) : base(null, rectT)
|
||||||
|
{
|
||||||
|
Content = new GUIFrame(new RectTransform(Vector2.One, rectT), style: null)
|
||||||
|
{
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update(float deltaTime)
|
||||||
|
{
|
||||||
|
base.Update(deltaTime);
|
||||||
|
|
||||||
|
foreach (GUIComponent child in Children)
|
||||||
|
{
|
||||||
|
if (child == Content) { continue; }
|
||||||
|
throw new InvalidOperationException($"Children were found in {nameof(GUIScissorComponent)}, Add them to {nameof(GUIScissorComponent)}.{nameof(Content)} instead.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ClampChildMouseRects(Content);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Draw(SpriteBatch spriteBatch)
|
||||||
|
{
|
||||||
|
if (!Visible) { return; }
|
||||||
|
|
||||||
|
Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle;
|
||||||
|
RasterizerState prevRasterizerState = spriteBatch.GraphicsDevice.RasterizerState;
|
||||||
|
|
||||||
|
spriteBatch.End();
|
||||||
|
spriteBatch.GraphicsDevice.ScissorRectangle = Rectangle.Intersect(prevScissorRect, Rect);
|
||||||
|
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
|
||||||
|
|
||||||
|
foreach (GUIComponent child in Content.Children)
|
||||||
|
{
|
||||||
|
if (!child.Visible) { continue; }
|
||||||
|
child.DrawManually(spriteBatch, alsoChildren: true, recursive: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
spriteBatch.End();
|
||||||
|
spriteBatch.GraphicsDevice.ScissorRectangle = prevScissorRect;
|
||||||
|
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: prevRasterizerState);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClampChildMouseRects(GUIComponent child)
|
||||||
|
{
|
||||||
|
child.ClampMouseRectToParent = true;
|
||||||
|
|
||||||
|
if (child is GUIListBox) { return; }
|
||||||
|
|
||||||
|
foreach (GUIComponent grandChild in child.Children)
|
||||||
|
{
|
||||||
|
ClampChildMouseRects(grandChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void AddToGUIUpdateList(bool ignoreChildren = false, int order = 0)
|
||||||
|
{
|
||||||
|
if (!Visible) { return; }
|
||||||
|
|
||||||
|
UpdateOrder = order;
|
||||||
|
GUI.AddToUpdateList(this);
|
||||||
|
|
||||||
|
if (ignoreChildren)
|
||||||
|
{
|
||||||
|
OnAddedToGUIUpdateList?.Invoke(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (GUIComponent child in Content.Children)
|
||||||
|
{
|
||||||
|
if (!child.Visible) { continue; }
|
||||||
|
child.AddToGUIUpdateList(false, order);
|
||||||
|
}
|
||||||
|
OnAddedToGUIUpdateList?.Invoke(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,6 +25,7 @@ namespace Barotrauma
|
|||||||
public ScalableFont SubHeadingFont { get; private set; }
|
public ScalableFont SubHeadingFont { get; private set; }
|
||||||
public ScalableFont DigitalFont { get; private set; }
|
public ScalableFont DigitalFont { get; private set; }
|
||||||
public ScalableFont HotkeyFont { get; private set; }
|
public ScalableFont HotkeyFont { get; private set; }
|
||||||
|
public ScalableFont MonospacedFont { get; private set; }
|
||||||
|
|
||||||
public Dictionary<ScalableFont, bool> ForceFontUpperCase
|
public Dictionary<ScalableFont, bool> ForceFontUpperCase
|
||||||
{
|
{
|
||||||
@@ -40,12 +41,17 @@ namespace Barotrauma
|
|||||||
public SpriteSheet SavingIndicator { get; private set; }
|
public SpriteSheet SavingIndicator { get; private set; }
|
||||||
|
|
||||||
public UISprite UIGlow { get; private set; }
|
public UISprite UIGlow { get; private set; }
|
||||||
|
|
||||||
|
public UISprite PingCircle { get; private set; }
|
||||||
|
|
||||||
public UISprite UIGlowCircular { get; private set; }
|
public UISprite UIGlowCircular { get; private set; }
|
||||||
|
|
||||||
public UISprite ButtonPulse { get; private set; }
|
public UISprite ButtonPulse { get; private set; }
|
||||||
|
|
||||||
public SpriteSheet FocusIndicator { get; private set; }
|
public SpriteSheet FocusIndicator { get; private set; }
|
||||||
|
|
||||||
|
public UISprite IconOverflowIndicator { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// General green color used for elements whose colors are set from code
|
/// General green color used for elements whose colors are set from code
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -235,6 +241,9 @@ namespace Barotrauma
|
|||||||
case "uiglow":
|
case "uiglow":
|
||||||
UIGlow = new UISprite(subElement);
|
UIGlow = new UISprite(subElement);
|
||||||
break;
|
break;
|
||||||
|
case "pingcircle":
|
||||||
|
PingCircle = new UISprite(subElement);
|
||||||
|
break;
|
||||||
case "radiation":
|
case "radiation":
|
||||||
RadiationSprite = new UISprite(subElement);
|
RadiationSprite = new UISprite(subElement);
|
||||||
break;
|
break;
|
||||||
@@ -247,6 +256,9 @@ namespace Barotrauma
|
|||||||
case "endroundbuttonpulse":
|
case "endroundbuttonpulse":
|
||||||
ButtonPulse = new UISprite(subElement);
|
ButtonPulse = new UISprite(subElement);
|
||||||
break;
|
break;
|
||||||
|
case "iconoverflowindicator":
|
||||||
|
IconOverflowIndicator = new UISprite(subElement);
|
||||||
|
break;
|
||||||
case "focusindicator":
|
case "focusindicator":
|
||||||
FocusIndicator = new SpriteSheet(subElement);
|
FocusIndicator = new SpriteSheet(subElement);
|
||||||
break;
|
break;
|
||||||
@@ -277,6 +289,10 @@ namespace Barotrauma
|
|||||||
DigitalFont = LoadFont(subElement, graphicsDevice);
|
DigitalFont = LoadFont(subElement, graphicsDevice);
|
||||||
ForceFontUpperCase[DigitalFont] = subElement.GetAttributeBool("forceuppercase", false);
|
ForceFontUpperCase[DigitalFont] = subElement.GetAttributeBool("forceuppercase", false);
|
||||||
break;
|
break;
|
||||||
|
case "monospacedfont":
|
||||||
|
MonospacedFont = LoadFont(subElement, graphicsDevice);
|
||||||
|
ForceFontUpperCase[MonospacedFont] = subElement.GetAttributeBool("forceuppercase", false);
|
||||||
|
break;
|
||||||
case "hotkeyfont":
|
case "hotkeyfont":
|
||||||
HotkeyFont = LoadFont(subElement, graphicsDevice);
|
HotkeyFont = LoadFont(subElement, graphicsDevice);
|
||||||
ForceFontUpperCase[HotkeyFont] = subElement.GetAttributeBool("forceuppercase", false);
|
ForceFontUpperCase[HotkeyFont] = subElement.GetAttributeBool("forceuppercase", false);
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ namespace Barotrauma
|
|||||||
if (GUI.MouseOn != null) { return false; }
|
if (GUI.MouseOn != null) { return false; }
|
||||||
|
|
||||||
//don't close when hovering over an inventory element
|
//don't close when hovering over an inventory element
|
||||||
if (Inventory.IsMouseOnInventory()) { return false; }
|
if (Inventory.IsMouseOnInventory) { return false; }
|
||||||
|
|
||||||
bool input = PlayerInput.PrimaryMouseButtonDown() || PlayerInput.SecondaryMouseButtonClicked();
|
bool input = PlayerInput.PrimaryMouseButtonDown() || PlayerInput.SecondaryMouseButtonClicked();
|
||||||
return input && !rect.Contains(PlayerInput.MousePosition);
|
return input && !rect.Contains(PlayerInput.MousePosition);
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ namespace Barotrauma
|
|||||||
if (LoadState == 100.0f)
|
if (LoadState == 100.0f)
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
if (GameMain.Config.AutomaticQuickStartEnabled || GameMain.Config.AutomaticCampaignLoadEnabled && GameMain.FirstLoad)
|
if (GameMain.Config.AutomaticQuickStartEnabled || GameMain.Config.AutomaticCampaignLoadEnabled || GameMain.Config.TestScreenEnabled && GameMain.FirstLoad)
|
||||||
{
|
{
|
||||||
loadText = "QUICKSTARTING ...";
|
loadText = "QUICKSTARTING ...";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,14 +55,47 @@ namespace Barotrauma
|
|||||||
var texture = GetTexture(spriteBatch);
|
var texture = GetTexture(spriteBatch);
|
||||||
|
|
||||||
for (var i = 0; i < points.Count - 1; i++)
|
for (var i = 0; i < points.Count - 1; i++)
|
||||||
DrawPolygonEdge(spriteBatch, texture, points[i] + offset, points[i + 1] + offset, color, thickness);
|
DrawPolygonEdge(spriteBatch, points[i] + offset, points[i + 1] + offset, color, thickness);
|
||||||
|
|
||||||
DrawPolygonEdge(spriteBatch, texture, points[points.Count - 1] + offset, points[0] + offset, color,
|
DrawPolygonEdge(spriteBatch, points[points.Count - 1] + offset, points[0] + offset, color,
|
||||||
thickness);
|
thickness);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DrawPolygonEdge(SpriteBatch spriteBatch, Texture2D texture, Vector2 point1, Vector2 point2,
|
/// <summary>
|
||||||
Color color, float thickness)
|
/// Draws a closed polygon from an array of points
|
||||||
|
/// </summary>
|
||||||
|
public static void DrawPolygonInner(this SpriteBatch spriteBatch, Vector2 offset, IReadOnlyList<Vector2> points, Color color, float thickness = 1f)
|
||||||
|
{
|
||||||
|
if (points.Count == 0) { return; }
|
||||||
|
|
||||||
|
if (points.Count == 1)
|
||||||
|
{
|
||||||
|
DrawPoint(spriteBatch, points[0], color, (int)thickness);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < points.Count - 1; i++)
|
||||||
|
{
|
||||||
|
Vector2 point1 = points[i] + offset,
|
||||||
|
point2 = points[i + 1] + offset;
|
||||||
|
|
||||||
|
DrawPolygonEdgeInner(spriteBatch, point1, point2, color, thickness);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawPolygonEdgeInner(spriteBatch, points[^1] + offset, points[0] + offset, color, thickness);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DrawPolygonEdgeInner(SpriteBatch spriteBatch, Vector2 point1, Vector2 point2, Color color, float thickness)
|
||||||
|
{
|
||||||
|
var length = Vector2.Distance(point1, point2) + thickness;
|
||||||
|
var angle = (float)Math.Atan2(point2.Y - point1.Y, point2.X - point1.X);
|
||||||
|
var scale = new Vector2(length, thickness);
|
||||||
|
Vector2 middle = new Vector2((point1.X + point2.X) / 2f, (point1.Y + point2.Y) / 2f);
|
||||||
|
Texture2D tex = GetTexture(spriteBatch);
|
||||||
|
spriteBatch.Draw(GetTexture(spriteBatch), middle, null, color, angle, new Vector2(tex.Width / 2f, tex.Height / 2f), scale, SpriteEffects.None, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DrawPolygonEdge(SpriteBatch spriteBatch, Vector2 point1, Vector2 point2, Color color, float thickness)
|
||||||
{
|
{
|
||||||
var length = Vector2.Distance(point1, point2);
|
var length = Vector2.Distance(point1, point2);
|
||||||
var angle = (float)Math.Atan2(point2.Y - point1.Y, point2.X - point1.X);
|
var angle = (float)Math.Atan2(point2.Y - point1.Y, point2.X - point1.X);
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace Barotrauma
|
|||||||
private Color storeSpecialColor;
|
private Color storeSpecialColor;
|
||||||
|
|
||||||
private GUIListBox shoppingCrateBuyList, shoppingCrateSellList, shoppingCrateSellFromSubList;
|
private GUIListBox shoppingCrateBuyList, shoppingCrateSellList, shoppingCrateSellFromSubList;
|
||||||
private GUITextBlock shoppingCrateTotal;
|
private GUITextBlock relevantBalanceName, shoppingCrateTotal;
|
||||||
private GUIButton clearAllButton, confirmButton;
|
private GUIButton clearAllButton, confirmButton;
|
||||||
|
|
||||||
private bool needsRefresh, needsBuyingRefresh, needsSellingRefresh, needsItemsToSellRefresh, needsSellingFromSubRefresh, needsItemsToSellFromSubRefresh;
|
private bool needsRefresh, needsBuyingRefresh, needsSellingRefresh, needsItemsToSellRefresh, needsSellingFromSubRefresh, needsItemsToSellFromSubRefresh;
|
||||||
@@ -58,7 +58,6 @@ namespace Barotrauma
|
|||||||
StoreTab.SellFromSub => false,
|
StoreTab.SellFromSub => false,
|
||||||
_ => throw new NotImplementedException()
|
_ => throw new NotImplementedException()
|
||||||
};
|
};
|
||||||
private bool IsSelling => !IsBuying;
|
|
||||||
private GUIListBox ActiveShoppingCrateList => activeTab switch
|
private GUIListBox ActiveShoppingCrateList => activeTab switch
|
||||||
{
|
{
|
||||||
StoreTab.Buy => shoppingCrateBuyList,
|
StoreTab.Buy => shoppingCrateBuyList,
|
||||||
@@ -222,16 +221,8 @@ namespace Barotrauma
|
|||||||
TextScale = 1.1f,
|
TextScale = 1.1f,
|
||||||
TextGetter = () =>
|
TextGetter = () =>
|
||||||
{
|
{
|
||||||
if (CurrentLocation != null)
|
merchantBalanceBlock.TextColor = CurrentLocation?.BalanceColor ?? Color.Red;
|
||||||
{
|
return GetMerchantBalanceText();
|
||||||
merchantBalanceBlock.TextColor = CurrentLocation.BalanceColor;
|
|
||||||
return GetCurrencyFormatted(CurrentLocation.StoreCurrentBalance);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
merchantBalanceBlock.TextColor = Color.Red;
|
|
||||||
return GetCurrencyFormatted(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -375,28 +366,37 @@ namespace Barotrauma
|
|||||||
//don't show categories with no buyable items
|
//don't show categories with no buyable items
|
||||||
itemCategories.RemoveAll(c => !ItemPrefab.Prefabs.Any(ep => ep.Category.HasFlag(c) && ep.CanBeBought));
|
itemCategories.RemoveAll(c => !ItemPrefab.Prefabs.Any(ep => ep.Category.HasFlag(c) && ep.CanBeBought));
|
||||||
itemCategoryButtons.Clear();
|
itemCategoryButtons.Clear();
|
||||||
|
var categoryButton = new GUIButton(new RectTransform(new Point(categoryButtonContainer.Rect.Width, categoryButtonContainer.Rect.Width), categoryButtonContainer.RectTransform), style: "CategoryButton.All")
|
||||||
|
{
|
||||||
|
ToolTip = TextManager.Get("MapEntityCategory.All"),
|
||||||
|
OnClicked = OnClickedCategoryButton
|
||||||
|
};
|
||||||
|
itemCategoryButtons.Add(categoryButton);
|
||||||
foreach (MapEntityCategory category in itemCategories)
|
foreach (MapEntityCategory category in itemCategories)
|
||||||
{
|
{
|
||||||
var categoryButton = new GUIButton(new RectTransform(new Point(categoryButtonContainer.Rect.Width, categoryButtonContainer.Rect.Width), categoryButtonContainer.RectTransform),
|
categoryButton = new GUIButton(new RectTransform(new Point(categoryButtonContainer.Rect.Width, categoryButtonContainer.Rect.Width), categoryButtonContainer.RectTransform),
|
||||||
style: "CategoryButton." + category)
|
style: "CategoryButton." + category)
|
||||||
{
|
{
|
||||||
ToolTip = TextManager.Get("MapEntityCategory." + category),
|
ToolTip = TextManager.Get("MapEntityCategory." + category),
|
||||||
UserData = category,
|
UserData = category,
|
||||||
OnClicked = (btn, userdata) =>
|
OnClicked = OnClickedCategoryButton
|
||||||
{
|
|
||||||
MapEntityCategory? newCategory = !btn.Selected ? (MapEntityCategory?)userdata : null;
|
|
||||||
if (newCategory.HasValue) { searchBox.Text = ""; }
|
|
||||||
if (newCategory != selectedItemCategory) { tabLists[activeTab].ScrollBar.BarScroll = 0f; }
|
|
||||||
FilterStoreItems(newCategory, searchBox.Text);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
itemCategoryButtons.Add(categoryButton);
|
itemCategoryButtons.Add(categoryButton);
|
||||||
categoryButton.RectTransform.SizeChanged += () =>
|
}
|
||||||
|
bool OnClickedCategoryButton(GUIButton button, object userData)
|
||||||
|
{
|
||||||
|
MapEntityCategory? newCategory = !button.Selected ? (MapEntityCategory?)userData : null;
|
||||||
|
if (newCategory.HasValue) { searchBox.Text = ""; }
|
||||||
|
if (newCategory != selectedItemCategory) { tabLists[activeTab].ScrollBar.BarScroll = 0f; }
|
||||||
|
FilterStoreItems(newCategory, searchBox.Text);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
foreach (var btn in itemCategoryButtons)
|
||||||
|
{
|
||||||
|
btn.RectTransform.SizeChanged += () =>
|
||||||
{
|
{
|
||||||
var sprite = categoryButton.Frame.sprites[GUIComponent.ComponentState.None].First();
|
var sprite = btn.Frame.sprites[GUIComponent.ComponentState.None].First();
|
||||||
categoryButton.RectTransform.NonScaledSize =
|
btn.RectTransform.NonScaledSize = new Point(btn.Rect.Width, (int)(btn.Rect.Width * ((float)sprite.Sprite.SourceRect.Height / sprite.Sprite.SourceRect.Width)));
|
||||||
new Point(categoryButton.Rect.Width, (int)(categoryButton.Rect.Width * ((float)sprite.Sprite.SourceRect.Height / sprite.Sprite.SourceRect.Width)));
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -503,11 +503,11 @@ namespace Barotrauma
|
|||||||
ForceUpperCase = true
|
ForceUpperCase = true
|
||||||
};
|
};
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), playerBalanceContainer.RectTransform),
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), playerBalanceContainer.RectTransform),
|
||||||
"", font: GUI.SubHeadingFont, textAlignment: Alignment.TopRight)
|
"", textColor: Color.White, font: GUI.SubHeadingFont, textAlignment: Alignment.TopRight)
|
||||||
{
|
{
|
||||||
AutoScaleVertical = true,
|
AutoScaleVertical = true,
|
||||||
TextScale = 1.1f,
|
TextScale = 1.1f,
|
||||||
TextGetter = () => GetCurrencyFormatted(PlayerMoney)
|
TextGetter = GetPlayerBalanceText
|
||||||
};
|
};
|
||||||
|
|
||||||
// Divider ------------------------------------------------
|
// Divider ------------------------------------------------
|
||||||
@@ -523,7 +523,7 @@ namespace Barotrauma
|
|||||||
RelativeSpacing = 0.015f,
|
RelativeSpacing = 0.015f,
|
||||||
Stretch = true
|
Stretch = true
|
||||||
};
|
};
|
||||||
var shoppingCrateListContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.85f), shoppingCrateInventoryContainer.RectTransform), style: null);
|
var shoppingCrateListContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.8f), shoppingCrateInventoryContainer.RectTransform), style: null);
|
||||||
shoppingCrateBuyList = new GUIListBox(new RectTransform(Vector2.One, shoppingCrateListContainer.RectTransform)) { Visible = false };
|
shoppingCrateBuyList = new GUIListBox(new RectTransform(Vector2.One, shoppingCrateListContainer.RectTransform)) { Visible = false };
|
||||||
shoppingCrateSellList = new GUIListBox(new RectTransform(Vector2.One, shoppingCrateListContainer.RectTransform)) { Visible = false };
|
shoppingCrateSellList = new GUIListBox(new RectTransform(Vector2.One, shoppingCrateListContainer.RectTransform)) { Visible = false };
|
||||||
if (GameMain.IsSingleplayer)
|
if (GameMain.IsSingleplayer)
|
||||||
@@ -531,6 +531,21 @@ namespace Barotrauma
|
|||||||
shoppingCrateSellFromSubList = new GUIListBox(new RectTransform(Vector2.One, shoppingCrateListContainer.RectTransform)) { Visible = false };
|
shoppingCrateSellFromSubList = new GUIListBox(new RectTransform(Vector2.One, shoppingCrateListContainer.RectTransform)) { Visible = false };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var relevantBalanceContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), shoppingCrateInventoryContainer.RectTransform), isHorizontal: true)
|
||||||
|
{
|
||||||
|
Stretch = true
|
||||||
|
};
|
||||||
|
relevantBalanceName = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), relevantBalanceContainer.RectTransform), "", font: GUI.Font)
|
||||||
|
{
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), relevantBalanceContainer.RectTransform), "", textColor: Color.White, font: GUI.SubHeadingFont, textAlignment: Alignment.Right)
|
||||||
|
{
|
||||||
|
CanBeFocused = false,
|
||||||
|
TextScale = 1.1f,
|
||||||
|
TextGetter = () => IsBuying ? GetPlayerBalanceText() : GetMerchantBalanceText()
|
||||||
|
};
|
||||||
|
|
||||||
var totalContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), shoppingCrateInventoryContainer.RectTransform), isHorizontal: true)
|
var totalContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), shoppingCrateInventoryContainer.RectTransform), isHorizontal: true)
|
||||||
{
|
{
|
||||||
Stretch = true
|
Stretch = true
|
||||||
@@ -576,6 +591,10 @@ namespace Barotrauma
|
|||||||
resolutionWhenCreated = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
resolutionWhenCreated = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GetMerchantBalanceText() => GetCurrencyFormatted(CurrentLocation?.StoreCurrentBalance ?? 0);
|
||||||
|
|
||||||
|
private string GetPlayerBalanceText() => GetCurrencyFormatted(PlayerMoney);
|
||||||
|
|
||||||
private GUILayoutGroup CreateDealsGroup(GUIListBox parentList)
|
private GUILayoutGroup CreateDealsGroup(GUIListBox parentList)
|
||||||
{
|
{
|
||||||
var elementHeight = (int)(GUI.yScale * 80);
|
var elementHeight = (int)(GUI.yScale * 80);
|
||||||
@@ -604,17 +623,14 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
prevLocation.Reputation.OnReputationValueChanged = null;
|
prevLocation.Reputation.OnReputationValueChanged = null;
|
||||||
}
|
}
|
||||||
|
if (ItemPrefab.Prefabs.Any(p => p.CanBeBoughtAtLocation(CurrentLocation, out PriceInfo _)))
|
||||||
foreach (ItemPrefab itemPrefab in ItemPrefab.Prefabs)
|
|
||||||
{
|
{
|
||||||
if (itemPrefab.CanBeBoughtAtLocation(CurrentLocation, out PriceInfo _))
|
selectedItemCategory = null;
|
||||||
|
searchBox.Text = "";
|
||||||
|
ChangeStoreTab(StoreTab.Buy);
|
||||||
|
if (newLocation?.Reputation != null)
|
||||||
{
|
{
|
||||||
ChangeStoreTab(StoreTab.Buy);
|
newLocation.Reputation.OnReputationValueChanged += () => { needsRefresh = true; };
|
||||||
if (newLocation?.Reputation != null)
|
|
||||||
{
|
|
||||||
newLocation.Reputation.OnReputationValueChanged += () => { needsRefresh = true; };
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -628,6 +644,7 @@ namespace Barotrauma
|
|||||||
tabButton.Selected = (StoreTab)tabButton.UserData == activeTab;
|
tabButton.Selected = (StoreTab)tabButton.UserData == activeTab;
|
||||||
}
|
}
|
||||||
sortingDropDown.SelectItem(tabSortingMethods[tab]);
|
sortingDropDown.SelectItem(tabSortingMethods[tab]);
|
||||||
|
relevantBalanceName.Text = IsBuying ? TextManager.Get("campaignstore.balance") : TextManager.Get("campaignstore.storebalance");
|
||||||
SetShoppingCrateTotalText();
|
SetShoppingCrateTotalText();
|
||||||
SetClearAllButtonStatus();
|
SetClearAllButtonStatus();
|
||||||
SetConfirmButtonBehavior();
|
SetConfirmButtonBehavior();
|
||||||
@@ -697,7 +714,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
foreach (GUIButton btn in itemCategoryButtons)
|
foreach (GUIButton btn in itemCategoryButtons)
|
||||||
{
|
{
|
||||||
btn.Selected = category.HasValue && (MapEntityCategory)btn.UserData == selectedItemCategory;
|
btn.Selected = (MapEntityCategory?)btn.UserData == selectedItemCategory;
|
||||||
}
|
}
|
||||||
list.UpdateScrollBarSize();
|
list.UpdateScrollBarSize();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace Barotrauma
|
|||||||
private static UISprite spectateIcon, disconnectedIcon;
|
private static UISprite spectateIcon, disconnectedIcon;
|
||||||
private static Sprite ownerIcon, moderatorIcon;
|
private static Sprite ownerIcon, moderatorIcon;
|
||||||
|
|
||||||
private enum InfoFrameTab { Crew, Mission, Reputation, MyCharacter, Traitor, Submarine };
|
private enum InfoFrameTab { Crew, Mission, Reputation, MyCharacter, Traitor, Submarine, Talents };
|
||||||
private static InfoFrameTab selectedTab;
|
private static InfoFrameTab selectedTab;
|
||||||
private GUIFrame infoFrame, contentFrame;
|
private GUIFrame infoFrame, contentFrame;
|
||||||
|
|
||||||
@@ -258,6 +258,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
var myCharacterButton = createTabButton(InfoFrameTab.MyCharacter, "tabmenu.character");
|
var myCharacterButton = createTabButton(InfoFrameTab.MyCharacter, "tabmenu.character");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var talentsButton = createTabButton(InfoFrameTab.Talents, "tabmenu.talents");
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool SelectInfoFrameTab(GUIButton button, object userData)
|
private bool SelectInfoFrameTab(GUIButton button, object userData)
|
||||||
@@ -296,6 +298,9 @@ namespace Barotrauma
|
|||||||
case InfoFrameTab.Submarine:
|
case InfoFrameTab.Submarine:
|
||||||
CreateSubmarineInfo(infoFrameHolder, Submarine.MainSub);
|
CreateSubmarineInfo(infoFrameHolder, Submarine.MainSub);
|
||||||
break;
|
break;
|
||||||
|
case InfoFrameTab.Talents:
|
||||||
|
CreateTalentInfo(infoFrameHolder);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -1159,5 +1164,319 @@ namespace Barotrauma
|
|||||||
sub.Info.CreateSpecsWindow(specsListBox, GUI.Font, includeTitle: false, includeClass: false, includeDescription: true);
|
sub.Info.CreateSpecsWindow(specsListBox, GUI.Font, includeTitle: false, includeClass: false, includeDescription: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private Color unselectedColor = new Color(240, 255, 255, 225);
|
||||||
|
private Color selectedColor = new Color(220, 255, 220, 225);
|
||||||
|
private Color ownedColor = new Color(140, 180, 140, 225);
|
||||||
|
private Color unselectableColor = new Color(100, 100, 100, 225);
|
||||||
|
private Color pressedColor = new Color(60, 60, 60, 225);
|
||||||
|
|
||||||
|
private readonly List<(GUIButton button, GUIImage background, GUIImage icon)> talentButtons = new List<(GUIButton button, GUIImage background, GUIImage icon)>();
|
||||||
|
private List<string> selectedTalents = new List<string>();
|
||||||
|
private GUITextBlock talentTitleText;
|
||||||
|
private GUITextBlock talentDescriptionText;
|
||||||
|
private GUITextBlock talentPointsText;
|
||||||
|
|
||||||
|
private GUITextBlock experienceText;
|
||||||
|
private Color experienceBackgroundColor = new Color(255, 255, 255, 155);
|
||||||
|
|
||||||
|
private GUIProgressBar experienceBar;
|
||||||
|
|
||||||
|
private void CreateTalentInfo(GUIFrame infoFrame)
|
||||||
|
{
|
||||||
|
infoFrame.ClearChildren();
|
||||||
|
talentButtons.Clear();
|
||||||
|
|
||||||
|
GUIFrame talentFrameBackground = new GUIFrame(new RectTransform(Vector2.One, infoFrame.RectTransform, Anchor.TopCenter), style: "GUIFrameListBox");
|
||||||
|
int padding = GUI.IntScale(15);
|
||||||
|
GUIFrame talentFrameContent = new GUIFrame(new RectTransform(new Point(talentFrameBackground.Rect.Width - padding, talentFrameBackground.Rect.Height - padding), infoFrame.RectTransform, Anchor.Center), style: null);
|
||||||
|
|
||||||
|
Character controlledCharacter = Character.Controlled;
|
||||||
|
|
||||||
|
if (controlledCharacter.Info == null)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("No character info found for talent UI");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedTalents = controlledCharacter.Info.UnlockedTalents.ToList();
|
||||||
|
|
||||||
|
GUILayoutGroup talentFrameLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), talentFrameContent.RectTransform, anchor: Anchor.Center), childAnchor: Anchor.TopCenter)
|
||||||
|
{
|
||||||
|
AbsoluteSpacing = GUI.IntScale(5)
|
||||||
|
};
|
||||||
|
|
||||||
|
GUILayoutGroup talentInfoLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.325f), talentFrameLayoutGroup.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter);
|
||||||
|
|
||||||
|
GUIFrame talentTitleFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.25f), talentInfoLayoutGroup.RectTransform, Anchor.TopCenter), style: null);
|
||||||
|
|
||||||
|
talentTitleText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), talentTitleFrame.RectTransform, Anchor.TopLeft), "", font: GUI.LargeFont);
|
||||||
|
talentPointsText = new GUITextBlock(new RectTransform(new Vector2(0.25f, 1.0f), talentTitleFrame.RectTransform, Anchor.TopRight), "", font: GUI.Font, textAlignment: Alignment.Center);
|
||||||
|
|
||||||
|
GUIFrame talentDescriptionFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.4f), talentInfoLayoutGroup.RectTransform, Anchor.TopCenter), style: null);
|
||||||
|
|
||||||
|
talentDescriptionText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), talentDescriptionFrame.RectTransform, Anchor.TopLeft), "", font: GUI.Font, textAlignment: Alignment.TopLeft, wrap: true);
|
||||||
|
|
||||||
|
GUIFrame characterInfoFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.3f), talentInfoLayoutGroup.RectTransform, Anchor.TopLeft), style: null);
|
||||||
|
GUILayoutGroup characterInfoColumn = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), characterInfoFrame.RectTransform, anchor: Anchor.TopLeft), childAnchor: Anchor.TopLeft, isHorizontal: true);
|
||||||
|
|
||||||
|
CreateCharacterSheet(characterInfoColumn);
|
||||||
|
|
||||||
|
if (!TalentTree.JobTalentTrees.TryGetValue(controlledCharacter.Info.Job.Prefab.Identifier, out TalentTree talentTree)) { return; }
|
||||||
|
|
||||||
|
GUIListBox talentTreeListBox = new GUIListBox(new RectTransform(new Vector2(1f, 0.6f), talentFrameLayoutGroup.RectTransform, Anchor.TopCenter), isHorizontal: true, style: null);
|
||||||
|
|
||||||
|
int spacing = GUI.IntScale(5);
|
||||||
|
|
||||||
|
foreach (var subTree in talentTree.TalentSubTrees)
|
||||||
|
{
|
||||||
|
GUIFrame subTreeFrame = new GUIFrame(new RectTransform(new Vector2(0.333f, 1f), talentTreeListBox.Content.RectTransform, anchor: Anchor.TopLeft), style: null);
|
||||||
|
GUILayoutGroup subTreeLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1f, 1f), subTreeFrame.RectTransform, Anchor.Center), false, childAnchor: Anchor.TopCenter);
|
||||||
|
|
||||||
|
GUIFrame subtreeTitleFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.111f), subTreeLayoutGroup.RectTransform, anchor: Anchor.TopCenter), style: "SubtreeHeader");
|
||||||
|
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), subtreeTitleFrame.RectTransform, anchor: Anchor.TopCenter), subTree.Identifier, font: GUI.LargeFont, textAlignment: Alignment.Center);
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
GUIFrame talentOptionFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.222f), subTreeLayoutGroup.RectTransform, anchor: Anchor.TopCenter), style: "TalentOptionFrame");
|
||||||
|
GUIImage talentBackground = new GUIImage(new RectTransform(Vector2.One, talentOptionFrame.RectTransform, anchor: Anchor.Center), style: "TalentBackground")
|
||||||
|
{
|
||||||
|
CanBeFocused = false,
|
||||||
|
Color = unselectableColor,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (subTree.TalentOptionStages.Count > i)
|
||||||
|
{
|
||||||
|
TalentOption talentOption = subTree.TalentOptionStages[i];
|
||||||
|
|
||||||
|
GUILayoutGroup talentOptionLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1f, 1f), talentOptionFrame.RectTransform, Anchor.CenterLeft), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||||
|
{
|
||||||
|
Stretch = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (Talent talent in talentOption.Talents)
|
||||||
|
{
|
||||||
|
int optionPadding = GUI.IntScale(10);
|
||||||
|
GUIFrame talentFrame = new GUIFrame(new RectTransform(new Point(talentOptionFrame.Rect.Width, talentOptionFrame.Rect.Height - optionPadding), talentOptionLayoutGroup.RectTransform), style: null)
|
||||||
|
{
|
||||||
|
CanBeFocused = false,
|
||||||
|
};
|
||||||
|
new GUIImage(new RectTransform(Vector2.One, talentFrame.RectTransform, anchor: Anchor.Center), style: "TalentFrameBackground")
|
||||||
|
{
|
||||||
|
CanBeFocused = false,
|
||||||
|
};
|
||||||
|
GUIImage iconImage = null;
|
||||||
|
|
||||||
|
GUIButton talentButton = new GUIButton(new RectTransform(Vector2.One, talentFrame.RectTransform, anchor: Anchor.Center), style: "TalentFrame")
|
||||||
|
{
|
||||||
|
ToolTip = $"{TextManager.Get("talentname." + talent.Identifier, returnNull: true) ?? talent.Identifier} \n\n{TextManager.Get("talentdescription." + talent.Identifier, returnNull: true) ?? string.Empty}",
|
||||||
|
UserData = talent.Identifier,
|
||||||
|
PressedColor = pressedColor,
|
||||||
|
OnClicked = (button, userData) =>
|
||||||
|
{
|
||||||
|
talentTitleText.Text = TextManager.Get("talentname." + talent.Identifier, returnNull: true) ?? string.Empty;
|
||||||
|
talentDescriptionText.Text = TextManager.Get("talentdescription." + talent.Identifier, returnNull: true) ?? string.Empty;
|
||||||
|
|
||||||
|
// deselect other buttons in tier by removing their selected talents from pool
|
||||||
|
foreach (GUIButton guiButton in talentOptionLayoutGroup.GetAllChildren<GUIButton>())
|
||||||
|
{
|
||||||
|
if (guiButton.UserData is string otherTalentIdentifier && guiButton != button)
|
||||||
|
{
|
||||||
|
if (!controlledCharacter.HasTalent(otherTalentIdentifier))
|
||||||
|
{
|
||||||
|
selectedTalents.Remove(otherTalentIdentifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
string talentIdentifier = userData as string;
|
||||||
|
|
||||||
|
if (TalentTree.IsViableTalentForCharacter(controlledCharacter, talentIdentifier, selectedTalents))
|
||||||
|
{
|
||||||
|
if (!selectedTalents.Contains(talentIdentifier))
|
||||||
|
{
|
||||||
|
selectedTalents.Add(talentIdentifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!controlledCharacter.HasTalent(talentIdentifier))
|
||||||
|
{
|
||||||
|
selectedTalents.Remove(talentIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateTalentButtons();
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int iconPadding = GUI.IntScale(15);
|
||||||
|
iconImage = new GUIImage(new RectTransform(new Point(talentFrame.Rect.Width - iconPadding, talentFrame.Rect.Height - iconPadding), talentFrame.RectTransform, anchor: Anchor.Center), sprite: talent.Icon, scaleToFit: true)
|
||||||
|
{
|
||||||
|
PressedColor = unselectableColor,
|
||||||
|
CanBeFocused = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
talentButtons.Add((talentButton, talentBackground, iconImage));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GUIFrame talentBottomFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.07f), talentFrameLayoutGroup.RectTransform, Anchor.TopCenter), style: null);
|
||||||
|
|
||||||
|
GUIFrame experienceBarFrame = new GUIFrame(new RectTransform(new Vector2(0.775f, 0.75f), talentBottomFrame.RectTransform, Anchor.TopCenter), style: null);
|
||||||
|
|
||||||
|
experienceBar = new GUIProgressBar(new RectTransform(new Vector2(1f, 1f), experienceBarFrame.RectTransform, Anchor.CenterLeft),
|
||||||
|
barSize: controlledCharacter.Info.GetProgressTowardsNextLevel(), color: Color.White, style: "ExperienceBar")
|
||||||
|
{
|
||||||
|
IsHorizontal = true
|
||||||
|
};
|
||||||
|
|
||||||
|
GUIImage experienceTextBackground = new GUIImage(new RectTransform(new Vector2(0.2f, 0.475f), experienceBarFrame.RectTransform, anchor: Anchor.Center), style: "ExperienceTextBackground");
|
||||||
|
|
||||||
|
experienceText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), experienceTextBackground.RectTransform, anchor: Anchor.Center), "", font: GUI.Font, textColor: Color.White, textAlignment: Alignment.Center);
|
||||||
|
|
||||||
|
new GUIButton(new RectTransform(new Vector2(0.1f, 0.3f), talentBottomFrame.RectTransform, anchor: Anchor.TopRight), text: TextManager.Get("applysettingsbutton"))
|
||||||
|
{
|
||||||
|
OnClicked = ApplyTalentSelection,
|
||||||
|
};
|
||||||
|
|
||||||
|
new GUIButton(new RectTransform(new Vector2(0.1f, 0.3f), talentBottomFrame.RectTransform, anchor: Anchor.TopLeft), text: TextManager.Get("reset"))
|
||||||
|
{
|
||||||
|
OnClicked = ResetTalentSelection,
|
||||||
|
};
|
||||||
|
|
||||||
|
UpdateTalentButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateTalentButtons()
|
||||||
|
{
|
||||||
|
Character controlledCharacter = Character.Controlled;
|
||||||
|
|
||||||
|
talentPointsText.Text = $"{TextManager.Get("talentpointsleft")}{controlledCharacter.Info.GetAvailableTalentPoints()}";
|
||||||
|
experienceText.Text = $"{controlledCharacter.Info.ExperiencePoints - controlledCharacter.Info.GetExperienceRequiredForCurrentLevel()} / {controlledCharacter.Info.GetExperienceRequiredToLevelUp() - controlledCharacter.Info.GetExperienceRequiredForCurrentLevel()}";
|
||||||
|
experienceBar.BarSize = controlledCharacter.Info.GetProgressTowardsNextLevel();
|
||||||
|
//experienceBar.ToolTip = $"{controlledCharacter.Info.ExperiencePoints - controlledCharacter.Info.GetExperienceRequiredForCurrentLevel()} / {controlledCharacter.Info.GetExperienceRequiredToLevelUp() - controlledCharacter.Info.GetExperienceRequiredForCurrentLevel()}";
|
||||||
|
|
||||||
|
selectedTalents = TalentTree.CheckTalentSelection(controlledCharacter, selectedTalents);
|
||||||
|
|
||||||
|
foreach (var talentButton in talentButtons)
|
||||||
|
{
|
||||||
|
talentButton.background.Color = unselectableColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var talentButton in talentButtons)
|
||||||
|
{
|
||||||
|
string talentIdentifier = talentButton.button.UserData as string;
|
||||||
|
bool unselectable = !TalentTree.IsViableTalentForCharacter(controlledCharacter, talentIdentifier, selectedTalents) || controlledCharacter.HasTalent(talentIdentifier);
|
||||||
|
Color newTalentColor = unselectable ? unselectableColor : unselectedColor;
|
||||||
|
|
||||||
|
if (controlledCharacter.HasTalent(talentIdentifier))
|
||||||
|
{
|
||||||
|
newTalentColor = ownedColor;
|
||||||
|
}
|
||||||
|
else if (selectedTalents.Contains(talentIdentifier))
|
||||||
|
{
|
||||||
|
newTalentColor = selectedColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
talentButton.button.Color = newTalentColor;
|
||||||
|
talentButton.button.SelectedColor = newTalentColor;
|
||||||
|
talentButton.button.HoverColor = newTalentColor;
|
||||||
|
talentButton.button.DisabledColor = newTalentColor;
|
||||||
|
|
||||||
|
talentButton.icon.Color = newTalentColor;
|
||||||
|
|
||||||
|
// update background color as well, if not defined yet
|
||||||
|
if (talentButton.background.Color == unselectableColor)
|
||||||
|
{
|
||||||
|
talentButton.background.Color = newTalentColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void ApplyTalents(Character controlledCharacter)
|
||||||
|
{
|
||||||
|
selectedTalents = TalentTree.CheckTalentSelection(controlledCharacter, selectedTalents);
|
||||||
|
foreach (string talent in selectedTalents)
|
||||||
|
{
|
||||||
|
controlledCharacter.GiveTalent(talent);
|
||||||
|
if (GameMain.Client != null)
|
||||||
|
{
|
||||||
|
GameMain.Client.CreateEntityEvent(controlledCharacter, new object[] { NetEntityEvent.Type.UpdateTalents });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UpdateTalentButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ApplyTalentSelection(GUIButton guiButton, object userData)
|
||||||
|
{
|
||||||
|
Character controlledCharacter = Character.Controlled;
|
||||||
|
ApplyTalents(controlledCharacter);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ResetTalentSelection(GUIButton guiButton, object userData)
|
||||||
|
{
|
||||||
|
Character controlledCharacter = Character.Controlled;
|
||||||
|
selectedTalents = controlledCharacter.Info.UnlockedTalents.ToList();
|
||||||
|
UpdateTalentButtons();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnExperienceChanged(Character character)
|
||||||
|
{
|
||||||
|
if (character != Character.Controlled) { return; }
|
||||||
|
UpdateTalentButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly StatTypes[] basicStats = new StatTypes[]
|
||||||
|
{
|
||||||
|
StatTypes.MaximumHealthMultiplier,
|
||||||
|
StatTypes.MovementSpeed,
|
||||||
|
StatTypes.SwimmingSpeed,
|
||||||
|
StatTypes.RepairSpeed,
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly StatTypes[] combatStats = new StatTypes[]
|
||||||
|
{
|
||||||
|
StatTypes.MaximumHealthMultiplier,
|
||||||
|
StatTypes.MovementSpeed,
|
||||||
|
StatTypes.SwimmingSpeed,
|
||||||
|
StatTypes.RepairSpeed,
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly StatTypes[] miscStats = new StatTypes[]
|
||||||
|
{
|
||||||
|
StatTypes.ReputationGainMultiplier,
|
||||||
|
StatTypes.MissionMoneyGainMultiplier,
|
||||||
|
StatTypes.ExperienceGainMultiplier,
|
||||||
|
StatTypes.MissionExperienceGainMultiplier,
|
||||||
|
};
|
||||||
|
|
||||||
|
private void CreateCharacterSheet(GUILayoutGroup characterInfoColumn)
|
||||||
|
{
|
||||||
|
Character controlledCharacter = Character.Controlled;
|
||||||
|
|
||||||
|
CreateRow(basicStats);
|
||||||
|
CreateRow(combatStats);
|
||||||
|
CreateRow(miscStats);
|
||||||
|
|
||||||
|
void CreateRow(StatTypes[] statTypes)
|
||||||
|
{
|
||||||
|
GUILayoutGroup characterInfoRow = new GUILayoutGroup(new RectTransform(new Vector2(0.33f, 1.0f), characterInfoColumn.RectTransform, anchor: Anchor.TopLeft), childAnchor: Anchor.TopCenter);
|
||||||
|
foreach (StatTypes statType in statTypes)
|
||||||
|
{
|
||||||
|
ShowStat(statType, characterInfoRow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowStat(StatTypes statType, GUILayoutGroup characterInfoRow)
|
||||||
|
{
|
||||||
|
GUIFrame textInfoFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.33f), characterInfoRow.RectTransform, Anchor.TopCenter), style: null);
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1f, 1f), textInfoFrame.RectTransform, Anchor.TopLeft), statType.ToString(), font: GUI.SmallFont, textAlignment: Alignment.TopLeft);
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1f, 1f), textInfoFrame.RectTransform, Anchor.TopLeft), (int)(100f * (1 + controlledCharacter.GetStatValue(statType))) + "%", font: GUI.Font, textAlignment: Alignment.TopRight);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,8 +115,9 @@ namespace Barotrauma
|
|||||||
return MathHelper.Clamp(Math.Min(Math.Min(scale.X, scale.Y), GUI.SlicedSpriteScale), minBorderScale, maxBorderScale);
|
return MathHelper.Clamp(Math.Min(Math.Min(scale.X, scale.Y), GUI.SlicedSpriteScale), minBorderScale, maxBorderScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Draw(SpriteBatch spriteBatch, Rectangle rect, Color color, SpriteEffects spriteEffects = SpriteEffects.None)
|
public void Draw(SpriteBatch spriteBatch, Rectangle rect, Color color, SpriteEffects spriteEffects = SpriteEffects.None, Vector2? uvOffset = null)
|
||||||
{
|
{
|
||||||
|
uvOffset ??= Vector2.Zero;
|
||||||
if (Sprite.Texture == null)
|
if (Sprite.Texture == null)
|
||||||
{
|
{
|
||||||
GUI.DrawRectangle(spriteBatch, rect, Color.Magenta);
|
GUI.DrawRectangle(spriteBatch, rect, Color.Magenta);
|
||||||
@@ -157,7 +158,7 @@ namespace Barotrauma
|
|||||||
else if (Tile)
|
else if (Tile)
|
||||||
{
|
{
|
||||||
Vector2 startPos = new Vector2(rect.X, rect.Y);
|
Vector2 startPos = new Vector2(rect.X, rect.Y);
|
||||||
Sprite.DrawTiled(spriteBatch, startPos, new Vector2(rect.Width, rect.Height), color);
|
Sprite.DrawTiled(spriteBatch, startPos, new Vector2(rect.Width, rect.Height), color, startOffset: uvOffset);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ namespace Barotrauma
|
|||||||
public static SteamWorkshopScreen SteamWorkshopScreen;
|
public static SteamWorkshopScreen SteamWorkshopScreen;
|
||||||
|
|
||||||
public static SubEditorScreen SubEditorScreen;
|
public static SubEditorScreen SubEditorScreen;
|
||||||
|
public static TestScreen TestScreen;
|
||||||
public static ParticleEditorScreen ParticleEditorScreen;
|
public static ParticleEditorScreen ParticleEditorScreen;
|
||||||
public static LevelEditorScreen LevelEditorScreen;
|
public static LevelEditorScreen LevelEditorScreen;
|
||||||
public static SpriteEditorScreen SpriteEditorScreen;
|
public static SpriteEditorScreen SpriteEditorScreen;
|
||||||
@@ -89,7 +90,16 @@ namespace Barotrauma
|
|||||||
public static ParticleManager ParticleManager;
|
public static ParticleManager ParticleManager;
|
||||||
public static DecalManager DecalManager;
|
public static DecalManager DecalManager;
|
||||||
|
|
||||||
public static World World;
|
private static World world;
|
||||||
|
public static World World
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (world == null) { world = new World(new Vector2(0, -9.82f)); }
|
||||||
|
return world;
|
||||||
|
}
|
||||||
|
set { world = value; }
|
||||||
|
}
|
||||||
|
|
||||||
public static LoadingScreen TitleScreen;
|
public static LoadingScreen TitleScreen;
|
||||||
private bool loadingScreenOpen;
|
private bool loadingScreenOpen;
|
||||||
@@ -239,7 +249,6 @@ namespace Barotrauma
|
|||||||
GameMain.ResetFrameTime();
|
GameMain.ResetFrameTime();
|
||||||
fixedTime = new GameTime();
|
fixedTime = new GameTime();
|
||||||
|
|
||||||
World = new World(new Vector2(0, -9.82f));
|
|
||||||
FarseerPhysics.Settings.AllowSleep = true;
|
FarseerPhysics.Settings.AllowSleep = true;
|
||||||
FarseerPhysics.Settings.ContinuousPhysics = false;
|
FarseerPhysics.Settings.ContinuousPhysics = false;
|
||||||
FarseerPhysics.Settings.VelocityIterations = 1;
|
FarseerPhysics.Settings.VelocityIterations = 1;
|
||||||
@@ -567,6 +576,8 @@ namespace Barotrauma
|
|||||||
ItemPrefab.LoadAll(GetFilesOfType(ContentType.Item));
|
ItemPrefab.LoadAll(GetFilesOfType(ContentType.Item));
|
||||||
AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions));
|
AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions));
|
||||||
SkillSettings.Load(GetFilesOfType(ContentType.SkillSettings));
|
SkillSettings.Load(GetFilesOfType(ContentType.SkillSettings));
|
||||||
|
TalentPrefab.LoadAll(GetFilesOfType(ContentType.Talents));
|
||||||
|
TalentTree.LoadAll(GetFilesOfType(ContentType.TalentTrees));
|
||||||
Order.Init();
|
Order.Init();
|
||||||
EventManagerSettings.Init();
|
EventManagerSettings.Init();
|
||||||
BallastFloraPrefab.LoadAll(GetFilesOfType(ContentType.MapCreature));
|
BallastFloraPrefab.LoadAll(GetFilesOfType(ContentType.MapCreature));
|
||||||
@@ -620,6 +631,7 @@ namespace Barotrauma
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
SubEditorScreen = new SubEditorScreen();
|
SubEditorScreen = new SubEditorScreen();
|
||||||
|
TestScreen = new TestScreen();
|
||||||
|
|
||||||
TitleScreen.LoadState = 75.0f;
|
TitleScreen.LoadState = 75.0f;
|
||||||
yield return CoroutineStatus.Running;
|
yield return CoroutineStatus.Running;
|
||||||
@@ -792,12 +804,16 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
if (TitleScreen.LoadState >= 100.0f && !TitleScreen.PlayingSplashScreen && (Config.AutomaticQuickStartEnabled || Config.AutomaticCampaignLoadEnabled) && FirstLoad && !PlayerInput.KeyDown(Keys.LeftShift))
|
if (TitleScreen.LoadState >= 100.0f && !TitleScreen.PlayingSplashScreen && (Config.AutomaticQuickStartEnabled || Config.AutomaticCampaignLoadEnabled || Config.TestScreenEnabled) && FirstLoad && !PlayerInput.KeyDown(Keys.LeftShift))
|
||||||
{
|
{
|
||||||
loadingScreenOpen = false;
|
loadingScreenOpen = false;
|
||||||
FirstLoad = false;
|
FirstLoad = false;
|
||||||
|
|
||||||
if (Config.AutomaticQuickStartEnabled)
|
if (Config.TestScreenEnabled)
|
||||||
|
{
|
||||||
|
TestScreen.Select();
|
||||||
|
}
|
||||||
|
else if (Config.AutomaticQuickStartEnabled)
|
||||||
{
|
{
|
||||||
MainMenuScreen.QuickStart();
|
MainMenuScreen.QuickStart();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,11 +48,7 @@ namespace Barotrauma
|
|||||||
var equipmentSlots = new List<InvSlotType>() { InvSlotType.Head, InvSlotType.InnerClothes, InvSlotType.OuterClothes, InvSlotType.Headset, InvSlotType.Card };
|
var equipmentSlots = new List<InvSlotType>() { InvSlotType.Head, InvSlotType.InnerClothes, InvSlotType.OuterClothes, InvSlotType.Headset, InvSlotType.Card };
|
||||||
return character.Inventory.FindAllItems(item =>
|
return character.Inventory.FindAllItems(item =>
|
||||||
{
|
{
|
||||||
if (item.SpawnedInOutpost) { return false; }
|
if (!IsItemSellable(item, confirmedSoldEntities)) { return false; }
|
||||||
if (!item.Prefab.AllowSellingWhenBroken && item.ConditionPercentage < 90.0f) { return false; }
|
|
||||||
if (confirmedSoldEntities.Any(it => it.Item == item)) { return false; }
|
|
||||||
// There must be no contained items or the contained items must be confirmed as sold
|
|
||||||
if (!item.ContainedItems.All(it => confirmedSoldEntities.Any(se => se.Item == it))) { return false; }
|
|
||||||
// Item must be in a non-equipment slot if possible
|
// Item must be in a non-equipment slot if possible
|
||||||
if (!item.AllowedSlots.All(s => equipmentSlots.Contains(s)) && IsInEquipmentSlot(item)) { return false; }
|
if (!item.AllowedSlots.All(s => equipmentSlots.Contains(s)) && IsInEquipmentSlot(item)) { return false; }
|
||||||
// Item must not be contained inside an item in an equipment slot
|
// Item must not be contained inside an item in an equipment slot
|
||||||
@@ -76,15 +72,10 @@ namespace Barotrauma
|
|||||||
var confirmedSoldEntities = GetConfirmedSoldEntities();
|
var confirmedSoldEntities = GetConfirmedSoldEntities();
|
||||||
return Submarine.MainSub.GetItems(true).FindAll(item =>
|
return Submarine.MainSub.GetItems(true).FindAll(item =>
|
||||||
{
|
{
|
||||||
if (!item.Prefab.CanBeSold) { return false; }
|
if (!IsItemSellable(item, confirmedSoldEntities)) { return false; }
|
||||||
if (item.SpawnedInOutpost) { return false; }
|
|
||||||
if (!item.Prefab.AllowSellingWhenBroken && item.ConditionPercentage < 90.0f) { return false; }
|
|
||||||
if (!item.Components.All(c => !(c is Holdable h) || !h.Attachable || !h.Attached)) { return false; }
|
if (!item.Components.All(c => !(c is Holdable h) || !h.Attachable || !h.Attached)) { return false; }
|
||||||
if (!item.Components.All(c => !(c is Wire w) || w.Connections.All(c => c == null))) { return false; }
|
if (!item.Components.All(c => !(c is Wire w) || w.Connections.All(c => c == null))) { return false; }
|
||||||
if (!ItemAndAllContainersInteractable(item)) { return false; }
|
if (!ItemAndAllContainersInteractable(item)) { return false; }
|
||||||
if (confirmedSoldEntities.Any(it => it.Item == item)) { return false; }
|
|
||||||
// There must be no contained items or the contained items must be confirmed as sold
|
|
||||||
if (!item.ContainedItems.All(it => confirmedSoldEntities.Any(se => se.Item == it))) { return false; }
|
|
||||||
return true;
|
return true;
|
||||||
}).Distinct();
|
}).Distinct();
|
||||||
|
|
||||||
@@ -107,6 +98,24 @@ namespace Barotrauma
|
|||||||
return SoldEntities.Where(se => se.Status != SoldEntity.SellStatus.Unconfirmed);
|
return SoldEntities.Where(se => se.Status != SoldEntity.SellStatus.Unconfirmed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsItemSellable(Item item, IEnumerable<SoldEntity> confirmedSoldEntities)
|
||||||
|
{
|
||||||
|
if (!item.Prefab.CanBeSold) { return false; }
|
||||||
|
if (item.SpawnedInOutpost) { return false; }
|
||||||
|
if (!item.Prefab.AllowSellingWhenBroken && item.ConditionPercentage < 90.0f) { return false; }
|
||||||
|
if (confirmedSoldEntities.Any(it => it.Item == item)) { return false; }
|
||||||
|
if (item.OwnInventory?.Container is ItemContainer itemContainer)
|
||||||
|
{
|
||||||
|
var containedItems = item.ContainedItems;
|
||||||
|
if (containedItems.None()) { return true; }
|
||||||
|
// Allow selling the item if contained items are unsellable and set to be removed on deconstruct
|
||||||
|
if (itemContainer.RemoveContainedItemsOnDeconstruct && containedItems.All(it => !it.Prefab.CanBeSold)) { return true; }
|
||||||
|
// Otherwise there must be no contained items or the contained items must be confirmed as sold
|
||||||
|
if (!containedItems.All(it => confirmedSoldEntities.Any(se => se.Item == it))) { return false; }
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public void SetItemsInBuyCrate(List<PurchasedItem> items)
|
public void SetItemsInBuyCrate(List<PurchasedItem> items)
|
||||||
{
|
{
|
||||||
ItemsInBuyCrate.Clear();
|
ItemsInBuyCrate.Clear();
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -761,7 +761,7 @@ namespace Barotrauma
|
|||||||
Faction faction = campaign.Factions.FirstOrDefault(f => f.Prefab.Identifier.Equals(identifier, StringComparison.OrdinalIgnoreCase));
|
Faction faction = campaign.Factions.FirstOrDefault(f => f.Prefab.Identifier.Equals(identifier, StringComparison.OrdinalIgnoreCase));
|
||||||
if (faction?.Reputation != null)
|
if (faction?.Reputation != null)
|
||||||
{
|
{
|
||||||
faction.Reputation.Value = rep;
|
faction.Reputation.SetReputation(rep);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -771,7 +771,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (reputation.HasValue)
|
if (reputation.HasValue)
|
||||||
{
|
{
|
||||||
campaign.Map.CurrentLocation.Reputation.Value = reputation.Value;
|
campaign.Map.CurrentLocation.Reputation.SetReputation(reputation.Value);
|
||||||
campaign?.CampaignUI?.UpgradeStore?.RefreshAll();
|
campaign?.CampaignUI?.UpgradeStore?.RefreshAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace Barotrauma
|
|||||||
if (GameMain.NetLobbyScreen.HeadSelectionList != null) { GameMain.NetLobbyScreen.HeadSelectionList.Visible = false; }
|
if (GameMain.NetLobbyScreen.HeadSelectionList != null) { GameMain.NetLobbyScreen.HeadSelectionList.Visible = false; }
|
||||||
if (GameMain.NetLobbyScreen.JobSelectionFrame != null) { GameMain.NetLobbyScreen.JobSelectionFrame.Visible = false; }
|
if (GameMain.NetLobbyScreen.JobSelectionFrame != null) { GameMain.NetLobbyScreen.JobSelectionFrame.Visible = false; }
|
||||||
}
|
}
|
||||||
if (tabMenu == null && GameMode is TutorialMode == false)
|
if (tabMenu == null && !(GameMode is TutorialMode) && !ConversationAction.IsDialogOpen)
|
||||||
{
|
{
|
||||||
tabMenu = new TabMenu();
|
tabMenu = new TabMenu();
|
||||||
HintManager.OnShowTabMenu();
|
HintManager.OnShowTabMenu();
|
||||||
@@ -34,7 +34,6 @@ namespace Barotrauma
|
|||||||
tabMenu = null;
|
tabMenu = null;
|
||||||
NetLobbyScreen.JobInfoFrame = null;
|
NetLobbyScreen.JobInfoFrame = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +43,7 @@ namespace Barotrauma
|
|||||||
private GUIComponent respawnInfoFrame, respawnButtonContainer;
|
private GUIComponent respawnInfoFrame, respawnButtonContainer;
|
||||||
private GUITextBlock respawnInfoText;
|
private GUITextBlock respawnInfoText;
|
||||||
private GUITickBox respawnTickBox;
|
private GUITickBox respawnTickBox;
|
||||||
private GUILayoutGroup TopLeftButtonGroup;
|
|
||||||
private void CreateTopLeftButtons()
|
private void CreateTopLeftButtons()
|
||||||
{
|
{
|
||||||
if (topLeftButtonGroup != null)
|
if (topLeftButtonGroup != null)
|
||||||
|
|||||||
@@ -1518,6 +1518,12 @@ namespace Barotrauma
|
|||||||
"Automatic quickstart enabled",
|
"Automatic quickstart enabled",
|
||||||
"Will the game automatically move on to Quickstart when the game is launched");
|
"Will the game automatically move on to Quickstart when the game is launched");
|
||||||
|
|
||||||
|
addDebugTickBox(
|
||||||
|
TestScreenEnabled,
|
||||||
|
(b) => TestScreenEnabled = b,
|
||||||
|
"Test screen enabled",
|
||||||
|
"Will the game automatically move on to a test screen when the game is launched");
|
||||||
|
|
||||||
addDebugTickBox(
|
addDebugTickBox(
|
||||||
AutomaticCampaignLoadEnabled,
|
AutomaticCampaignLoadEnabled,
|
||||||
(b) => AutomaticCampaignLoadEnabled = b,
|
(b) => AutomaticCampaignLoadEnabled = b,
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public override void CreateSlots()
|
public override void CreateSlots()
|
||||||
{
|
{
|
||||||
if (visualSlots == null) { visualSlots = new VisualSlot[capacity]; }
|
visualSlots ??= new VisualSlot[capacity];
|
||||||
|
|
||||||
float multiplier = !GUI.IsFourByThree() ? UIScale : UIScale * 0.925f;
|
float multiplier = !GUI.IsFourByThree() ? UIScale : UIScale * 0.925f;
|
||||||
|
|
||||||
@@ -359,7 +359,8 @@ namespace Barotrauma
|
|||||||
int personalSlotX = HUDLayoutSettings.InventoryAreaLower.Right - SlotSize.X - Spacing;
|
int personalSlotX = HUDLayoutSettings.InventoryAreaLower.Right - SlotSize.X - Spacing;
|
||||||
for (int i = 0; i < visualSlots.Length; i++)
|
for (int i = 0; i < visualSlots.Length; i++)
|
||||||
{
|
{
|
||||||
if (HideSlot(i)) continue;
|
if (HideSlot(i)) { continue; }
|
||||||
|
if (SlotTypes[i] == InvSlotType.RightHand || SlotTypes[i] == InvSlotType.LeftHand) { continue; }
|
||||||
if (PersonalSlots.HasFlag(SlotTypes[i]))
|
if (PersonalSlots.HasFlag(SlotTypes[i]))
|
||||||
{
|
{
|
||||||
//upperX -= slotSize.X + spacing;
|
//upperX -= slotSize.X + spacing;
|
||||||
@@ -371,10 +372,18 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
int lowerX = x;
|
int lowerX = x;
|
||||||
|
int handSlotX = x;
|
||||||
int personalSlotY = GameMain.GraphicsHeight - bottomOffset * 2 - Spacing * 2 - (int)(!GUI.IsFourByThree() ? UnequippedIndicator.size.Y * UIScale * IndicatorScaleAdjustment : UnequippedIndicator.size.Y * UIScale * IndicatorScaleAdjustment * 2f);
|
int personalSlotY = GameMain.GraphicsHeight - bottomOffset * 2 - Spacing * 2 - (int)(!GUI.IsFourByThree() ? UnequippedIndicator.size.Y * UIScale * IndicatorScaleAdjustment : UnequippedIndicator.size.Y * UIScale * IndicatorScaleAdjustment * 2f);
|
||||||
for (int i = 0; i < SlotPositions.Length; i++)
|
for (int i = 0; i < SlotPositions.Length; i++)
|
||||||
{
|
{
|
||||||
if (HideSlot(i)) continue;
|
if (SlotTypes[i] == InvSlotType.RightHand || SlotTypes[i] == InvSlotType.LeftHand)
|
||||||
|
{
|
||||||
|
SlotPositions[i] = new Vector2(handSlotX, personalSlotY);
|
||||||
|
handSlotX += visualSlots[i].Rect.Width + Spacing;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HideSlot(i)) { continue; }
|
||||||
if (PersonalSlots.HasFlag(SlotTypes[i]))
|
if (PersonalSlots.HasFlag(SlotTypes[i]))
|
||||||
{
|
{
|
||||||
SlotPositions[i] = new Vector2(personalSlotX, personalSlotY);
|
SlotPositions[i] = new Vector2(personalSlotX, personalSlotY);
|
||||||
@@ -390,7 +399,8 @@ namespace Barotrauma
|
|||||||
x = lowerX;
|
x = lowerX;
|
||||||
for (int i = 0; i < SlotPositions.Length; i++)
|
for (int i = 0; i < SlotPositions.Length; i++)
|
||||||
{
|
{
|
||||||
if (!HideSlot(i)) continue;
|
if (!HideSlot(i)) { continue; }
|
||||||
|
if (SlotTypes[i] == InvSlotType.RightHand || SlotTypes[i] == InvSlotType.LeftHand) { continue; }
|
||||||
x -= visualSlots[i].Rect.Width + Spacing;
|
x -= visualSlots[i].Rect.Width + Spacing;
|
||||||
SlotPositions[i] = new Vector2(x, GameMain.GraphicsHeight - bottomOffset);
|
SlotPositions[i] = new Vector2(x, GameMain.GraphicsHeight - bottomOffset);
|
||||||
}
|
}
|
||||||
@@ -404,7 +414,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
for (int i = 0; i < SlotPositions.Length; i++)
|
for (int i = 0; i < SlotPositions.Length; i++)
|
||||||
{
|
{
|
||||||
if (HideSlot(i)) continue;
|
if (HideSlot(i)) { continue; }
|
||||||
|
if (SlotTypes[i] == InvSlotType.RightHand || SlotTypes[i] == InvSlotType.LeftHand) { continue; }
|
||||||
if (PersonalSlots.HasFlag(SlotTypes[i]))
|
if (PersonalSlots.HasFlag(SlotTypes[i]))
|
||||||
{
|
{
|
||||||
SlotPositions[i] = new Vector2(personalSlotX, personalSlotY);
|
SlotPositions[i] = new Vector2(personalSlotX, personalSlotY);
|
||||||
@@ -416,9 +427,16 @@ namespace Barotrauma
|
|||||||
x += visualSlots[i].Rect.Width + Spacing;
|
x += visualSlots[i].Rect.Width + Spacing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
int handSlotX = x - visualSlots[0].Rect.Width - Spacing;
|
||||||
for (int i = 0; i < SlotPositions.Length; i++)
|
for (int i = 0; i < SlotPositions.Length; i++)
|
||||||
{
|
{
|
||||||
if (!HideSlot(i)) continue;
|
if (SlotTypes[i] == InvSlotType.RightHand || SlotTypes[i] == InvSlotType.LeftHand)
|
||||||
|
{
|
||||||
|
bool rightSlot = SlotTypes[i] == InvSlotType.RightHand;
|
||||||
|
SlotPositions[i] = new Vector2(rightSlot ? handSlotX : handSlotX - visualSlots[0].Rect.Width - Spacing, personalSlotY);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!HideSlot(i)) { continue; }
|
||||||
SlotPositions[i] = new Vector2(x, GameMain.GraphicsHeight - bottomOffset);
|
SlotPositions[i] = new Vector2(x, GameMain.GraphicsHeight - bottomOffset);
|
||||||
x += visualSlots[i].Rect.Width + Spacing;
|
x += visualSlots[i].Rect.Width + Spacing;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using System.Collections.Generic;
|
|||||||
using Barotrauma.IO;
|
using Barotrauma.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
using Barotrauma.Sounds;
|
||||||
|
|
||||||
namespace Barotrauma.Items.Components
|
namespace Barotrauma.Items.Components
|
||||||
{
|
{
|
||||||
@@ -18,7 +19,11 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
protected float currentCrossHairScale, currentCrossHairPointerScale;
|
protected float currentCrossHairScale, currentCrossHairPointerScale;
|
||||||
|
|
||||||
|
private RoundSound chargeSound;
|
||||||
|
private SoundChannel chargeSoundChannel;
|
||||||
|
|
||||||
private readonly List<ParticleEmitter> particleEmitters = new List<ParticleEmitter>();
|
private readonly List<ParticleEmitter> particleEmitters = new List<ParticleEmitter>();
|
||||||
|
private readonly List<ParticleEmitter> particleEmitterCharges = new List<ParticleEmitter>();
|
||||||
|
|
||||||
[Serialize(1.0f, false, description: "The scale of the crosshair sprite (if there is one).")]
|
[Serialize(1.0f, false, description: "The scale of the crosshair sprite (if there is one).")]
|
||||||
public float CrossHairScale
|
public float CrossHairScale
|
||||||
@@ -48,6 +53,12 @@ namespace Barotrauma.Items.Components
|
|||||||
case "particleemitter":
|
case "particleemitter":
|
||||||
particleEmitters.Add(new ParticleEmitter(subElement));
|
particleEmitters.Add(new ParticleEmitter(subElement));
|
||||||
break;
|
break;
|
||||||
|
case "particleemittercharge":
|
||||||
|
particleEmitterCharges.Add(new ParticleEmitter(subElement));
|
||||||
|
break;
|
||||||
|
case "chargesound":
|
||||||
|
chargeSound = Submarine.LoadRoundSound(subElement, false);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,6 +95,51 @@ namespace Barotrauma.Items.Components
|
|||||||
crosshairPointerPos = PlayerInput.MousePosition;
|
crosshairPointerPos = PlayerInput.MousePosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
partial void UpdateProjSpecific(float deltaTime)
|
||||||
|
{
|
||||||
|
float chargeRatio = currentChargeTime / MaxChargeTime;
|
||||||
|
|
||||||
|
switch (currentChargingState)
|
||||||
|
{
|
||||||
|
case ChargingState.WindingUp:
|
||||||
|
case ChargingState.WindingDown:
|
||||||
|
Vector2 particlePos = item.WorldPosition + ConvertUnits.ToDisplayUnits(TransformedBarrelPos);
|
||||||
|
float sizeMultiplier = Math.Clamp(chargeRatio, 0.1f, 1f);
|
||||||
|
foreach (ParticleEmitter emitter in particleEmitterCharges)
|
||||||
|
{
|
||||||
|
emitter.Emit(deltaTime, particlePos, hullGuess: null, sizeMultiplier: sizeMultiplier, colorMultiplier: emitter.Prefab.Properties.ColorMultiplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chargeSoundChannel == null || !chargeSoundChannel.IsPlaying)
|
||||||
|
{
|
||||||
|
if (chargeSound != null)
|
||||||
|
{
|
||||||
|
chargeSoundChannel = SoundPlayer.PlaySound(chargeSound.Sound, item.WorldPosition, chargeSound.Volume, chargeSound.Range, ignoreMuffling: chargeSound.IgnoreMuffling);
|
||||||
|
if (chargeSoundChannel != null) chargeSoundChannel.Looping = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (chargeSoundChannel != null)
|
||||||
|
{
|
||||||
|
chargeSoundChannel.FrequencyMultiplier = MathHelper.Lerp(0.5f, 1.5f, chargeRatio);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (chargeSoundChannel != null)
|
||||||
|
{
|
||||||
|
if (chargeSoundChannel.IsPlaying)
|
||||||
|
{
|
||||||
|
chargeSoundChannel.FadeOutAndDispose();
|
||||||
|
chargeSoundChannel.Looping = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
chargeSoundChannel = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||||
{
|
{
|
||||||
if (character == null || !character.IsKeyDown(InputType.Aim)) { return; }
|
if (character == null || !character.IsKeyDown(InputType.Aim)) { return; }
|
||||||
@@ -92,7 +148,7 @@ namespace Barotrauma.Items.Components
|
|||||||
if (character.ViewTarget != null && (character.ViewTarget is Item item) && item.Prefab.FocusOnSelected) { return; }
|
if (character.ViewTarget != null && (character.ViewTarget is Item item) && item.Prefab.FocusOnSelected) { return; }
|
||||||
|
|
||||||
GUI.HideCursor = (crosshairSprite != null || crosshairPointerSprite != null) &&
|
GUI.HideCursor = (crosshairSprite != null || crosshairPointerSprite != null) &&
|
||||||
GUI.MouseOn == null && !Inventory.IsMouseOnInventory() && !GameMain.Instance.Paused;
|
GUI.MouseOn == null && !Inventory.IsMouseOnInventory && !GameMain.Instance.Paused;
|
||||||
if (GUI.HideCursor)
|
if (GUI.HideCursor)
|
||||||
{
|
{
|
||||||
crosshairSprite?.Draw(spriteBatch, crosshairPos, Color.White, 0, currentCrossHairScale);
|
crosshairSprite?.Draw(spriteBatch, crosshairPos, Color.White, 0, currentCrossHairScale);
|
||||||
|
|||||||
@@ -246,6 +246,7 @@ namespace Barotrauma.Items.Components
|
|||||||
public void PlaySound(ActionType type, Character user = null)
|
public void PlaySound(ActionType type, Character user = null)
|
||||||
{
|
{
|
||||||
if (!hasSoundsOfType[(int)type]) { return; }
|
if (!hasSoundsOfType[(int)type]) { return; }
|
||||||
|
if (GameMain.Client?.MidRoundSyncing ?? false) { return; }
|
||||||
|
|
||||||
if (loopingSound != null)
|
if (loopingSound != null)
|
||||||
{
|
{
|
||||||
@@ -429,7 +430,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
foreach (ItemComponent component in item.Components)
|
foreach (ItemComponent component in item.Components)
|
||||||
{
|
{
|
||||||
if (component.name.ToLower() == LinkUIToComponent.ToLower())
|
if (component.name.Equals(LinkUIToComponent, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
linkToUIComponent = component;
|
linkToUIComponent = component;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,7 +126,8 @@ namespace Barotrauma.Items.Components
|
|||||||
private void DrawOverLay(SpriteBatch spriteBatch, GUICustomComponent overlayComponent)
|
private void DrawOverLay(SpriteBatch spriteBatch, GUICustomComponent overlayComponent)
|
||||||
{
|
{
|
||||||
overlayComponent.RectTransform.SetAsLastChild();
|
overlayComponent.RectTransform.SetAsLastChild();
|
||||||
var lastSlot = inputContainer.Inventory.visualSlots.Last();
|
if (!(inputContainer?.Inventory?.visualSlots is { } visualSlots)) { return; }
|
||||||
|
var lastSlot = visualSlots.Last();
|
||||||
|
|
||||||
GUI.DrawRectangle(spriteBatch,
|
GUI.DrawRectangle(spriteBatch,
|
||||||
new Rectangle(
|
new Rectangle(
|
||||||
|
|||||||
@@ -255,12 +255,15 @@ namespace Barotrauma.Items.Components
|
|||||||
var item1 = c1.GUIComponent.UserData as FabricationRecipe;
|
var item1 = c1.GUIComponent.UserData as FabricationRecipe;
|
||||||
var item2 = c2.GUIComponent.UserData as FabricationRecipe;
|
var item2 = c2.GUIComponent.UserData as FabricationRecipe;
|
||||||
|
|
||||||
bool hasSkills1 = FabricationDegreeOfSuccess(character, item1.RequiredSkills) >= 0.5f;
|
int itemPlacement1 = FabricationDegreeOfSuccess(character, item1.RequiredSkills) >= 0.5f ? 0 : -1;
|
||||||
bool hasSkills2 = FabricationDegreeOfSuccess(character, item2.RequiredSkills) >= 0.5f;
|
int itemPlacement2 = FabricationDegreeOfSuccess(character, item2.RequiredSkills) >= 0.5f ? 0 : -1;
|
||||||
|
|
||||||
if (hasSkills1 != hasSkills2)
|
itemPlacement1 += item1.RequiresRecipe && !character.HasRecipeForItem(item1.TargetItem.Identifier) ? -2 : 0;
|
||||||
|
itemPlacement2 += item2.RequiresRecipe && !character.HasRecipeForItem(item2.TargetItem.Identifier) ? -2 : 0;
|
||||||
|
|
||||||
|
if (itemPlacement1 != itemPlacement2)
|
||||||
{
|
{
|
||||||
return hasSkills1 ? -1 : 1;
|
return itemPlacement1 > itemPlacement2 ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return string.Compare(item1.DisplayName, item2.DisplayName);
|
return string.Compare(item1.DisplayName, item2.DisplayName);
|
||||||
@@ -285,6 +288,18 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
insufficientSkillsText.RectTransform.RepositionChildInHierarchy(itemList.Content.RectTransform.GetChildIndex(firstinSufficient.RectTransform));
|
insufficientSkillsText.RectTransform.RepositionChildInHierarchy(itemList.Content.RectTransform.GetChildIndex(firstinSufficient.RectTransform));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var requiresRecipeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), itemList.Content.RectTransform),
|
||||||
|
TextManager.Get("fabricatorrequiresrecipe", returnNull: true) ?? "Requires recipe to fabricate", textColor: Color.Red, font: GUI.SubHeadingFont)
|
||||||
|
{
|
||||||
|
AutoScaleHorizontal = true,
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
var firstRequiresRecipe = itemList.Content.Children.FirstOrDefault(c => c.UserData is FabricationRecipe fabricableItem && (fabricableItem.RequiresRecipe && !character.HasRecipeForItem(fabricableItem.TargetItem.Identifier)));
|
||||||
|
if (firstRequiresRecipe != null)
|
||||||
|
{
|
||||||
|
requiresRecipeText.RectTransform.RepositionChildInHierarchy(itemList.Content.RectTransform.GetChildIndex(firstRequiresRecipe.RectTransform));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawInputOverLay(SpriteBatch spriteBatch, GUICustomComponent overlayComponent)
|
private void DrawInputOverLay(SpriteBatch spriteBatch, GUICustomComponent overlayComponent)
|
||||||
@@ -297,6 +312,7 @@ namespace Barotrauma.Items.Components
|
|||||||
int slotIndex = 0;
|
int slotIndex = 0;
|
||||||
|
|
||||||
var missingItems = new List<FabricationRecipe.RequiredItem>();
|
var missingItems = new List<FabricationRecipe.RequiredItem>();
|
||||||
|
|
||||||
foreach (FabricationRecipe.RequiredItem requiredItem in targetItem.RequiredItems)
|
foreach (FabricationRecipe.RequiredItem requiredItem in targetItem.RequiredItems)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < requiredItem.Amount; i++)
|
for (int i = 0; i < requiredItem.Amount; i++)
|
||||||
@@ -308,6 +324,8 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
missingItems.Remove(missingItems.FirstOrDefault(mi => mi.ItemPrefabs.Contains(item.prefab)));
|
missingItems.Remove(missingItems.FirstOrDefault(mi => mi.ItemPrefabs.Contains(item.prefab)));
|
||||||
}
|
}
|
||||||
|
var missingCounts = missingItems.GroupBy(missingItem => missingItem).ToDictionary(x => x.Key, x => x.Count());
|
||||||
|
missingItems = missingItems.Distinct().ToList();
|
||||||
|
|
||||||
var availableIngredients = GetAvailableIngredients();
|
var availableIngredients = GetAvailableIngredients();
|
||||||
|
|
||||||
@@ -318,27 +336,27 @@ namespace Barotrauma.Items.Components
|
|||||||
slotIndex++;
|
slotIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
//highlight suitable ingredients in linked inventories
|
requiredItem.ItemPrefabs
|
||||||
foreach (Item item in availableIngredients)
|
.Where(requiredPrefab => availableIngredients.ContainsKey(requiredPrefab.Identifier))
|
||||||
{
|
.ForEach(requiredPrefab => {
|
||||||
if (item.ParentInventory != inputContainer.Inventory && IsItemValidIngredient(item, requiredItem))
|
var availablePrefabs = availableIngredients[requiredPrefab.Identifier];
|
||||||
{
|
|
||||||
int availableSlotIndex = item.ParentInventory.FindIndex(item);
|
availablePrefabs
|
||||||
//slots are null if the inventory has never been displayed
|
.Where(availablePrefab => availablePrefab.ParentInventory != inputContainer.Inventory)
|
||||||
//(linked item, but the UI is not set to be displayed at the same time)
|
.Where(availablePrefab => availablePrefab.ParentInventory.visualSlots != null) //slots are null if the inventory has never been displayed
|
||||||
if (item.ParentInventory.visualSlots != null)
|
.ForEach(availablePrefab => { //(linked item, but the UI is not set to be displayed at the same time)
|
||||||
{
|
int availableSlotIndex = availablePrefab.ParentInventory.FindIndex(availablePrefab);
|
||||||
if (item.ParentInventory.visualSlots[availableSlotIndex].HighlightTimer <= 0.0f)
|
|
||||||
{
|
if (availablePrefab.ParentInventory.visualSlots[availableSlotIndex].HighlightTimer <= 0.0f)
|
||||||
item.ParentInventory.visualSlots[availableSlotIndex].ShowBorderHighlight(GUI.Style.Green, 0.5f, 0.5f, 0.2f);
|
|
||||||
if (slotIndex < inputContainer.Capacity)
|
|
||||||
{
|
{
|
||||||
inputContainer.Inventory.visualSlots[slotIndex].ShowBorderHighlight(GUI.Style.Green, 0.5f, 0.5f, 0.2f);
|
availablePrefab.ParentInventory.visualSlots[availableSlotIndex].ShowBorderHighlight(GUI.Style.Green, 0.5f, 0.5f, 0.2f);
|
||||||
|
if (slotIndex < inputContainer.Capacity)
|
||||||
|
{
|
||||||
|
inputContainer.Inventory.visualSlots[slotIndex].ShowBorderHighlight(GUI.Style.Green, 0.5f, 0.5f, 0.2f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (slotIndex >= inputContainer.Capacity) { break; }
|
if (slotIndex >= inputContainer.Capacity) { break; }
|
||||||
|
|
||||||
@@ -350,6 +368,16 @@ namespace Barotrauma.Items.Components
|
|||||||
color: requiredItem.ItemPrefabs.First().InventoryIconColor * 0.3f,
|
color: requiredItem.ItemPrefabs.First().InventoryIconColor * 0.3f,
|
||||||
scale: Math.Min(slotRect.Width / itemIcon.size.X, slotRect.Height / itemIcon.size.Y));
|
scale: Math.Min(slotRect.Width / itemIcon.size.X, slotRect.Height / itemIcon.size.Y));
|
||||||
|
|
||||||
|
|
||||||
|
if (missingCounts[requiredItem] > 1)
|
||||||
|
{
|
||||||
|
Vector2 stackCountPos = new Vector2(slotRect.Right, slotRect.Bottom);
|
||||||
|
string stackCountText = "x" + missingCounts[requiredItem];
|
||||||
|
stackCountPos -= GUI.SmallFont.MeasureString(stackCountText) + new Vector2(4, 2);
|
||||||
|
GUI.SmallFont.DrawString(spriteBatch, stackCountText, stackCountPos + Vector2.One, Color.Black);
|
||||||
|
GUI.SmallFont.DrawString(spriteBatch, stackCountText, stackCountPos, Color.White);
|
||||||
|
}
|
||||||
|
|
||||||
if (requiredItem.UseCondition && requiredItem.MinCondition < 1.0f)
|
if (requiredItem.UseCondition && requiredItem.MinCondition < 1.0f)
|
||||||
{
|
{
|
||||||
GUI.DrawRectangle(spriteBatch, new Rectangle(slotRect.X, slotRect.Bottom - 8, slotRect.Width, 8), Color.Black * 0.8f, true);
|
GUI.DrawRectangle(spriteBatch, new Rectangle(slotRect.X, slotRect.Bottom - 8, slotRect.Width, 8), Color.Black * 0.8f, true);
|
||||||
@@ -601,7 +629,7 @@ namespace Barotrauma.Items.Components
|
|||||||
var itemPrefab = child.UserData as FabricationRecipe;
|
var itemPrefab = child.UserData as FabricationRecipe;
|
||||||
if (itemPrefab == null) continue;
|
if (itemPrefab == null) continue;
|
||||||
|
|
||||||
bool canBeFabricated = CanBeFabricated(itemPrefab, availableIngredients);
|
bool canBeFabricated = CanBeFabricated(itemPrefab, availableIngredients, character);
|
||||||
if (itemPrefab == selectedItem)
|
if (itemPrefab == selectedItem)
|
||||||
{
|
{
|
||||||
activateButton.Enabled = canBeFabricated;
|
activateButton.Enabled = canBeFabricated;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -142,6 +142,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
partial void UpdateProjSpecific(float deltaTime)
|
partial void UpdateProjSpecific(float deltaTime)
|
||||||
{
|
{
|
||||||
|
float rotationRad = MathHelper.ToRadians(item.Rotation);
|
||||||
if (FlowPercentage < 0.0f)
|
if (FlowPercentage < 0.0f)
|
||||||
{
|
{
|
||||||
foreach (var (position, emitter) in pumpOutEmitters)
|
foreach (var (position, emitter) in pumpOutEmitters)
|
||||||
@@ -150,11 +151,12 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
//only emit "pump out" particles when underwater
|
//only emit "pump out" particles when underwater
|
||||||
Vector2 relativeParticlePos = (item.WorldRect.Location.ToVector2() + position * item.Scale) - item.WorldPosition;
|
Vector2 relativeParticlePos = (item.WorldRect.Location.ToVector2() + position * item.Scale) - item.WorldPosition;
|
||||||
float angle = 0.0f;
|
relativeParticlePos = MathUtils.RotatePoint(relativeParticlePos, item.FlippedX ? rotationRad : -rotationRad);
|
||||||
|
float angle = -rotationRad;
|
||||||
if (item.FlippedX)
|
if (item.FlippedX)
|
||||||
{
|
{
|
||||||
relativeParticlePos.X = -relativeParticlePos.X;
|
relativeParticlePos.X = -relativeParticlePos.X;
|
||||||
angle = MathHelper.Pi;
|
angle += MathHelper.Pi;
|
||||||
}
|
}
|
||||||
if (item.FlippedY)
|
if (item.FlippedY)
|
||||||
{
|
{
|
||||||
@@ -170,11 +172,12 @@ namespace Barotrauma.Items.Components
|
|||||||
foreach (var (position, emitter) in pumpInEmitters)
|
foreach (var (position, emitter) in pumpInEmitters)
|
||||||
{
|
{
|
||||||
Vector2 relativeParticlePos = (item.WorldRect.Location.ToVector2() + position * item.Scale) - item.WorldPosition;
|
Vector2 relativeParticlePos = (item.WorldRect.Location.ToVector2() + position * item.Scale) - item.WorldPosition;
|
||||||
float angle = 0.0f;
|
relativeParticlePos = MathUtils.RotatePoint(relativeParticlePos, item.FlippedX ? rotationRad : -rotationRad);
|
||||||
|
float angle = -rotationRad;
|
||||||
if (item.FlippedX)
|
if (item.FlippedX)
|
||||||
{
|
{
|
||||||
relativeParticlePos.X = -relativeParticlePos.X;
|
relativeParticlePos.X = -relativeParticlePos.X;
|
||||||
angle = MathHelper.Pi;
|
angle += MathHelper.Pi;
|
||||||
}
|
}
|
||||||
if (item.FlippedY)
|
if (item.FlippedY)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -888,6 +888,7 @@ namespace Barotrauma.Items.Components
|
|||||||
maintainPosOriginIndicator?.Remove();
|
maintainPosOriginIndicator?.Remove();
|
||||||
steeringIndicator?.Remove();
|
steeringIndicator?.Remove();
|
||||||
enterOutpostPrompt?.Close();
|
enterOutpostPrompt?.Close();
|
||||||
|
pathFinder = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ namespace Barotrauma.Items.Components
|
|||||||
var chargeText = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1), textArea.RectTransform, Anchor.CenterRight),
|
var chargeText = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1), textArea.RectTransform, Anchor.CenterRight),
|
||||||
"", textColor: GUI.Style.TextColor, font: GUI.Font, textAlignment: Alignment.CenterRight)
|
"", textColor: GUI.Style.TextColor, font: GUI.Font, textAlignment: Alignment.CenterRight)
|
||||||
{
|
{
|
||||||
TextGetter = () => $"{(int)charge}/{(int)capacity} {kWmin} ({((int)MathUtils.Percentage(charge, capacity)).ToString()} %)"
|
TextGetter = () => $"{(int)Math.Round(charge)}/{(int)capacity} {kWmin} ({(int)Math.Round(MathUtils.Percentage(charge, capacity))} %)"
|
||||||
};
|
};
|
||||||
if (chargeText.TextSize.X > chargeText.Rect.Width) { chargeText.Font = GUI.SmallFont; }
|
if (chargeText.TextSize.X > chargeText.Rect.Width) { chargeText.Font = GUI.SmallFont; }
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
public GUIButton SabotageButton { get; private set; }
|
public GUIButton SabotageButton { get; private set; }
|
||||||
|
|
||||||
|
public GUIButton TinkerButton { get; private set; }
|
||||||
|
|
||||||
private GUIProgressBar progressBar;
|
private GUIProgressBar progressBar;
|
||||||
|
|
||||||
private List<ParticleEmitter> particleEmitters = new List<ParticleEmitter>();
|
private List<ParticleEmitter> particleEmitters = new List<ParticleEmitter>();
|
||||||
@@ -25,6 +27,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private string repairButtonText, repairingText;
|
private string repairButtonText, repairingText;
|
||||||
private string sabotageButtonText, sabotagingText;
|
private string sabotageButtonText, sabotagingText;
|
||||||
|
private string tinkerButtonText, tinkeringText;
|
||||||
|
|
||||||
private FixActions requestStartFixAction;
|
private FixActions requestStartFixAction;
|
||||||
|
|
||||||
@@ -46,7 +49,7 @@ namespace Barotrauma.Items.Components
|
|||||||
public override bool ShouldDrawHUD(Character character)
|
public override bool ShouldDrawHUD(Character character)
|
||||||
{
|
{
|
||||||
if (!HasRequiredItems(character, false) || character.SelectedConstruction != item) return false;
|
if (!HasRequiredItems(character, false) || character.SelectedConstruction != item) return false;
|
||||||
return item.ConditionPercentage < RepairThreshold || character.IsTraitor && item.ConditionPercentage > MinSabotageCondition || (CurrentFixer == character && (!item.IsFullCondition || (character.IsTraitor && item.ConditionPercentage > MinSabotageCondition)));
|
return item.ConditionPercentage < RepairThreshold || character.IsTraitor && item.ConditionPercentage > MinSabotageCondition || (CurrentFixer == character && (!item.IsFullCondition || (character.IsTraitor && item.ConditionPercentage > MinSabotageCondition))) || CanTinker(character);
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void InitProjSpecific(XElement element)
|
partial void InitProjSpecific(XElement element)
|
||||||
@@ -148,6 +151,20 @@ namespace Barotrauma.Items.Components
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
tinkerButtonText = "Tinker";
|
||||||
|
tinkeringText = "Tinkering";
|
||||||
|
TinkerButton = new GUIButton(new RectTransform(new Vector2(0.8f, 0.15f), paddedFrame.RectTransform, Anchor.BottomCenter), tinkerButtonText, style: "GUIButtonSmall")
|
||||||
|
{
|
||||||
|
IgnoreLayoutGroups = true,
|
||||||
|
Visible = false,
|
||||||
|
OnClicked = (btn, obj) =>
|
||||||
|
{
|
||||||
|
requestStartFixAction = FixActions.Tinker;
|
||||||
|
item.CreateClientEvent(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void UpdateProjSpecific(float deltaTime)
|
partial void UpdateProjSpecific(float deltaTime)
|
||||||
@@ -176,6 +193,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
case FixActions.Repair:
|
case FixActions.Repair:
|
||||||
case FixActions.Sabotage:
|
case FixActions.Sabotage:
|
||||||
|
case FixActions.Tinker:
|
||||||
StartRepairing(Character.Controlled, requestStartFixAction);
|
StartRepairing(Character.Controlled, requestStartFixAction);
|
||||||
requestStartFixAction = FixActions.None;
|
requestStartFixAction = FixActions.None;
|
||||||
break;
|
break;
|
||||||
@@ -226,6 +244,13 @@ namespace Barotrauma.Items.Components
|
|||||||
sabotageButtonText :
|
sabotageButtonText :
|
||||||
sabotagingText + new string('.', ((int)(Timing.TotalTime * 2.0f) % 3) + 1);
|
sabotagingText + new string('.', ((int)(Timing.TotalTime * 2.0f) % 3) + 1);
|
||||||
|
|
||||||
|
TinkerButton.Visible = CanTinker(character);
|
||||||
|
TinkerButton.IgnoreLayoutGroups = !TinkerButton.Visible;
|
||||||
|
TinkerButton.Enabled = (currentFixerAction == FixActions.None || (CurrentFixer == character && currentFixerAction != FixActions.Tinker)) && CanTinker(character);
|
||||||
|
TinkerButton.Text = (currentFixerAction == FixActions.None || CurrentFixer != character || currentFixerAction != FixActions.Tinker && CanTinker(character)) ?
|
||||||
|
tinkerButtonText :
|
||||||
|
tinkeringText + new string('.', ((int)(Timing.TotalTime * 2.0f) % 3) + 1);
|
||||||
|
|
||||||
System.Diagnostics.Debug.Assert(GuiFrame.GetChild(0) is GUILayoutGroup, "Repair UI hierarchy has changed, could not find skill texts");
|
System.Diagnostics.Debug.Assert(GuiFrame.GetChild(0) is GUILayoutGroup, "Repair UI hierarchy has changed, could not find skill texts");
|
||||||
foreach (GUIComponent c in GuiFrame.GetChild(0).Children)
|
foreach (GUIComponent c in GuiFrame.GetChild(0).Children)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ namespace Barotrauma.Items.Components
|
|||||||
GUITextBlock newBlock = new GUITextBlock(
|
GUITextBlock newBlock = new GUITextBlock(
|
||||||
new RectTransform(new Vector2(1, 0), historyBox.Content.RectTransform, anchor: Anchor.TopCenter),
|
new RectTransform(new Vector2(1, 0), historyBox.Content.RectTransform, anchor: Anchor.TopCenter),
|
||||||
"> " + input,
|
"> " + input,
|
||||||
textColor: Color.LimeGreen, wrap: true)
|
textColor: Color.LimeGreen, wrap: true, font: UseMonospaceFont ? GUI.MonospacedFont : GUI.GlobalFont)
|
||||||
{
|
{
|
||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -534,20 +534,20 @@ namespace Barotrauma.Items.Components
|
|||||||
minRotationWidget.Draw(spriteBatch, (float)Timing.Step);
|
minRotationWidget.Draw(spriteBatch, (float)Timing.Step);
|
||||||
maxRotationWidget.Draw(spriteBatch, (float)Timing.Step);
|
maxRotationWidget.Draw(spriteBatch, (float)Timing.Step);
|
||||||
|
|
||||||
Vector2 GetDrawPos()
|
|
||||||
{
|
|
||||||
Vector2 drawPos = new Vector2(item.Rect.X + transformedBarrelPos.X, item.Rect.Y - transformedBarrelPos.Y);
|
|
||||||
if (item.Submarine != null) { drawPos += item.Submarine.DrawPosition; }
|
|
||||||
drawPos.Y = -drawPos.Y;
|
|
||||||
return drawPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateBarrel()
|
void UpdateBarrel()
|
||||||
{
|
{
|
||||||
rotation = (minRotation + maxRotation) / 2;
|
rotation = (minRotation + maxRotation) / 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vector2 GetDrawPos()
|
||||||
|
{
|
||||||
|
Vector2 drawPos = new Vector2(item.Rect.X + transformedBarrelPos.X, item.Rect.Y - transformedBarrelPos.Y);
|
||||||
|
if (item.Submarine != null) { drawPos += item.Submarine.DrawPosition; }
|
||||||
|
drawPos.Y = -drawPos.Y;
|
||||||
|
return drawPos;
|
||||||
|
}
|
||||||
|
|
||||||
private Widget GetWidget(string id, SpriteBatch spriteBatch, int size = 5, float thickness = 1f, Action<Widget> initMethod = null)
|
private Widget GetWidget(string id, SpriteBatch spriteBatch, int size = 5, float thickness = 1f, Action<Widget> initMethod = null)
|
||||||
{
|
{
|
||||||
Vector2 offset = new Vector2(size / 2 + 5, -10);
|
Vector2 offset = new Vector2(size / 2 + 5, -10);
|
||||||
|
|||||||
@@ -478,7 +478,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (container == null) { return false; }
|
if (container == null) { return false; }
|
||||||
return owner.SelectedCharacter != null|| (!(owner is Character character)) || !container.KeepOpenWhenEquippedBy(character) || !owner.HasEquippedItem(container.Item);
|
return owner.SelectedCharacter != null|| (!(owner is Character character)) || !container.KeepOpenWhenEquippedBy(character) || !owner.HasEquippedItem(container.Item);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual bool HideSlot(int i)
|
protected virtual bool HideSlot(int i)
|
||||||
@@ -667,6 +667,10 @@ namespace Barotrauma
|
|||||||
if (subInventory.visualSlots == null) { subInventory.CreateSlots(); }
|
if (subInventory.visualSlots == null) { subInventory.CreateSlots(); }
|
||||||
|
|
||||||
canMove = container.MovableFrame && !subInventory.IsInventoryHoverAvailable(Owner as Character, container) && subInventory.originalPos != Point.Zero;
|
canMove = container.MovableFrame && !subInventory.IsInventoryHoverAvailable(Owner as Character, container) && subInventory.originalPos != Point.Zero;
|
||||||
|
if (this is CharacterInventory characterInventory && characterInventory.CurrentLayout != CharacterInventory.Layout.Default)
|
||||||
|
{
|
||||||
|
canMove = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (canMove)
|
if (canMove)
|
||||||
{
|
{
|
||||||
@@ -826,11 +830,23 @@ namespace Barotrauma
|
|||||||
return rect.Contains(PlayerInput.MousePosition);
|
return rect.Contains(PlayerInput.MousePosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool IsMouseOnInventory
|
||||||
|
{
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Refresh the value of IsMouseOnInventory
|
||||||
|
/// </summary>
|
||||||
|
public static void RefreshMouseOnInventory()
|
||||||
|
{
|
||||||
|
IsMouseOnInventory = DetermineMouseOnInventory();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Is the mouse on any inventory element (slot, equip button, subinventory...)
|
/// Is the mouse on any inventory element (slot, equip button, subinventory...)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
private static bool DetermineMouseOnInventory(bool ignoreDraggedItem = false)
|
||||||
public static bool IsMouseOnInventory(bool ignoreDraggedItem = false)
|
|
||||||
{
|
{
|
||||||
if (GameMain.GameSession?.Campaign != null &&
|
if (GameMain.GameSession?.Campaign != null &&
|
||||||
(GameMain.GameSession.Campaign.ShowCampaignUI || GameMain.GameSession.Campaign.ForceMapUI))
|
(GameMain.GameSession.Campaign.ShowCampaignUI || GameMain.GameSession.Campaign.ForceMapUI))
|
||||||
@@ -1112,7 +1128,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Character.Controlled.ClearInputs();
|
Character.Controlled.ClearInputs();
|
||||||
|
|
||||||
if (!IsMouseOnInventory(ignoreDraggedItem: true) &&
|
if (!DetermineMouseOnInventory(ignoreDraggedItem: true) &&
|
||||||
CharacterHealth.OpenHealthWindow != null)
|
CharacterHealth.OpenHealthWindow != null)
|
||||||
{
|
{
|
||||||
bool dropSuccessful = false;
|
bool dropSuccessful = false;
|
||||||
@@ -1306,7 +1322,9 @@ namespace Barotrauma
|
|||||||
protected static Rectangle GetSubInventoryHoverArea(SlotReference subSlot)
|
protected static Rectangle GetSubInventoryHoverArea(SlotReference subSlot)
|
||||||
{
|
{
|
||||||
Rectangle hoverArea;
|
Rectangle hoverArea;
|
||||||
if (!subSlot.Inventory.Movable() || Character.Controlled?.Inventory == subSlot.ParentInventory && !Character.Controlled.HasEquippedItem(subSlot.Item))
|
if (!subSlot.Inventory.Movable() ||
|
||||||
|
(Character.Controlled?.Inventory == subSlot.ParentInventory && !Character.Controlled.HasEquippedItem(subSlot.Item)) ||
|
||||||
|
(subSlot.ParentInventory is CharacterInventory characterInventory && characterInventory.CurrentLayout != CharacterInventory.Layout.Default))
|
||||||
{
|
{
|
||||||
hoverArea = subSlot.Slot.Rect;
|
hoverArea = subSlot.Slot.Rect;
|
||||||
hoverArea.Location += subSlot.Slot.DrawOffset.ToPoint();
|
hoverArea.Location += subSlot.Slot.DrawOffset.ToPoint();
|
||||||
|
|||||||
@@ -332,7 +332,7 @@ namespace Barotrauma
|
|||||||
foreach (var decorativeSprite in Prefab.DecorativeSprites)
|
foreach (var decorativeSprite in Prefab.DecorativeSprites)
|
||||||
{
|
{
|
||||||
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
||||||
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, spriteAnimState[decorativeSprite].RandomOffsetMultiplier, -rotationRad) * Scale;
|
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, spriteAnimState[decorativeSprite].RandomOffsetMultiplier, flippedX && Prefab.CanSpriteFlipX ? rotationRad : -rotationRad) * Scale;
|
||||||
if (flippedX && Prefab.CanSpriteFlipX) { offset.X = -offset.X; }
|
if (flippedX && Prefab.CanSpriteFlipX) { offset.X = -offset.X; }
|
||||||
if (flippedY && Prefab.CanSpriteFlipY) { offset.Y = -offset.Y; }
|
if (flippedY && Prefab.CanSpriteFlipY) { offset.Y = -offset.Y; }
|
||||||
decorativeSprite.Sprite.DrawTiled(spriteBatch,
|
decorativeSprite.Sprite.DrawTiled(spriteBatch,
|
||||||
@@ -368,7 +368,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
||||||
float rot = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState, spriteAnimState[decorativeSprite].RandomRotationFactor);
|
float rot = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState, spriteAnimState[decorativeSprite].RandomRotationFactor);
|
||||||
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, spriteAnimState[decorativeSprite].RandomOffsetMultiplier, -rotationRad) * Scale;
|
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, spriteAnimState[decorativeSprite].RandomOffsetMultiplier, flippedX && Prefab.CanSpriteFlipX ? rotationRad : -rotationRad) * Scale;
|
||||||
if (flippedX && Prefab.CanSpriteFlipX) { offset.X = -offset.X; }
|
if (flippedX && Prefab.CanSpriteFlipX) { offset.X = -offset.X; }
|
||||||
if (flippedY && Prefab.CanSpriteFlipY) { offset.Y = -offset.Y; }
|
if (flippedY && Prefab.CanSpriteFlipY) { offset.Y = -offset.Y; }
|
||||||
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + offset.X, -(DrawPosition.Y + offset.Y)), color,
|
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + offset.X, -(DrawPosition.Y + offset.Y)), color,
|
||||||
@@ -1623,6 +1623,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
wifiComponent.TeamID = (CharacterTeamType)teamID;
|
wifiComponent.TeamID = (CharacterTeamType)teamID;
|
||||||
}
|
}
|
||||||
|
foreach (IdCard idCard in item.GetComponents<IdCard>())
|
||||||
|
{
|
||||||
|
idCard.TeamID = (CharacterTeamType)teamID;
|
||||||
|
}
|
||||||
if (descriptionChanged) { item.Description = itemDesc; }
|
if (descriptionChanged) { item.Description = itemDesc; }
|
||||||
if (tagsChanged) { item.Tags = tags; }
|
if (tagsChanged) { item.Tags = tags; }
|
||||||
var nameTag = item.GetComponent<NameTag>();
|
var nameTag = item.GetComponent<NameTag>();
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
partial void ExplodeProjSpecific(Vector2 worldPosition, Hull hull)
|
partial void ExplodeProjSpecific(Vector2 worldPosition, Hull hull)
|
||||||
{
|
{
|
||||||
|
if (GameMain.Client?.MidRoundSyncing ?? false) { return; }
|
||||||
|
|
||||||
if (shockwave)
|
if (shockwave)
|
||||||
{
|
{
|
||||||
GameMain.ParticleManager.CreateParticle("shockwave", worldPosition,
|
GameMain.ParticleManager.CreateParticle("shockwave", worldPosition,
|
||||||
|
|||||||
@@ -676,7 +676,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
remoteBackgroundSections.Add(new BackgroundSection(new Rectangle(0, 0, 1, 1), i, colorStrength, color, 0));
|
remoteBackgroundSections.Add(new BackgroundSection(new Rectangle(0, 0, 1, 1), (ushort)i, colorStrength, color, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
paintAmount = BackgroundSections.Sum(s => s.ColorStrength);
|
paintAmount = BackgroundSections.Sum(s => s.ColorStrength);
|
||||||
|
|||||||
@@ -238,13 +238,13 @@ namespace Barotrauma.Lights
|
|||||||
//draw a black rectangle on hulls to hide background lights behind subs
|
//draw a black rectangle on hulls to hide background lights behind subs
|
||||||
//---------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
if (backgroundObstructor != null)
|
/*if (backgroundObstructor != null)
|
||||||
{
|
{
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);
|
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);
|
||||||
spriteBatch.Draw(backgroundObstructor, new Rectangle(0, 0,
|
spriteBatch.Draw(backgroundObstructor, new Rectangle(0, 0,
|
||||||
(int)(GameMain.GraphicsWidth * currLightMapScale), (int)(GameMain.GraphicsHeight * currLightMapScale)), Color.Black);
|
(int)(GameMain.GraphicsWidth * currLightMapScale), (int)(GameMain.GraphicsHeight * currLightMapScale)), Color.Black);
|
||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
}
|
}*/
|
||||||
|
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, transformMatrix: spriteBatchTransform);
|
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, transformMatrix: spriteBatchTransform);
|
||||||
Dictionary<Hull, Rectangle> visibleHulls = GetVisibleHulls(cam);
|
Dictionary<Hull, Rectangle> visibleHulls = GetVisibleHulls(cam);
|
||||||
@@ -258,7 +258,7 @@ namespace Barotrauma.Lights
|
|||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
|
|
||||||
SolidColorEffect.CurrentTechnique = SolidColorEffect.Techniques["SolidColor"];
|
SolidColorEffect.CurrentTechnique = SolidColorEffect.Techniques["SolidColor"];
|
||||||
SolidColorEffect.Parameters["color"].SetValue(AmbientLight.ToVector4());
|
SolidColorEffect.Parameters["color"].SetValue(AmbientLight.Opaque().ToVector4());
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, transformMatrix: spriteBatchTransform, effect: SolidColorEffect);
|
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, transformMatrix: spriteBatchTransform, effect: SolidColorEffect);
|
||||||
Submarine.DrawDamageable(spriteBatch, null);
|
Submarine.DrawDamageable(spriteBatch, null);
|
||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using Microsoft.Xna.Framework.Graphics;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
using Barotrauma.IO;
|
using Barotrauma.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
@@ -403,6 +404,8 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO remove
|
||||||
|
[Obsolete("Use MiniMap.CreateMiniMap()")]
|
||||||
public void CreateMiniMap(GUIComponent parent, IEnumerable<Entity> pointsOfInterest = null, bool ignoreOutpost = false)
|
public void CreateMiniMap(GUIComponent parent, IEnumerable<Entity> pointsOfInterest = null, bool ignoreOutpost = false)
|
||||||
{
|
{
|
||||||
Rectangle worldBorders = GetDockedBorders();
|
Rectangle worldBorders = GetDockedBorders();
|
||||||
@@ -417,24 +420,125 @@ namespace Barotrauma
|
|||||||
GUIFrame hullContainer = new GUIFrame(new RectTransform(
|
GUIFrame hullContainer = new GUIFrame(new RectTransform(
|
||||||
(parentAspectRatio > aspectRatio ? new Vector2(aspectRatio / parentAspectRatio, 1.0f) : new Vector2(1.0f, parentAspectRatio / aspectRatio)) * scale,
|
(parentAspectRatio > aspectRatio ? new Vector2(aspectRatio / parentAspectRatio, 1.0f) : new Vector2(1.0f, parentAspectRatio / aspectRatio)) * scale,
|
||||||
parent.RectTransform, Anchor.Center),
|
parent.RectTransform, Anchor.Center),
|
||||||
style: null);
|
style: null)
|
||||||
|
{
|
||||||
|
UserData = "hullcontainer"
|
||||||
|
};
|
||||||
|
|
||||||
var connectedSubs = GetConnectedSubs();
|
var connectedSubs = GetConnectedSubs();
|
||||||
foreach (Hull hull in Hull.hullList)
|
|
||||||
{
|
|
||||||
if (hull.Submarine != this && !connectedSubs.Contains(hull.Submarine)) { continue; }
|
|
||||||
if (ignoreOutpost && !IsEntityFoundOnThisSub(hull, true)) { continue; }
|
|
||||||
|
|
||||||
|
HashSet<Hull> hullList = Hull.hullList.Where(hull => hull.Submarine == this || connectedSubs.Contains(hull.Submarine)).Where(hull => !ignoreOutpost || IsEntityFoundOnThisSub(hull, true)).ToHashSet();
|
||||||
|
|
||||||
|
Dictionary<Hull, HashSet<Hull>> combinedHulls = new Dictionary<Hull, HashSet<Hull>>();
|
||||||
|
|
||||||
|
foreach (Hull hull in hullList)
|
||||||
|
{
|
||||||
|
if (combinedHulls.ContainsKey(hull) || combinedHulls.Values.Any(hh => hh.Contains(hull))) { continue; }
|
||||||
|
|
||||||
|
List<Hull> linkedHulls = new List<Hull>();
|
||||||
|
MiniMap.GetLinkedHulls(hull, linkedHulls);
|
||||||
|
|
||||||
|
linkedHulls.Remove(hull);
|
||||||
|
|
||||||
|
foreach (Hull linkedHull in linkedHulls)
|
||||||
|
{
|
||||||
|
if (!combinedHulls.ContainsKey(hull))
|
||||||
|
{
|
||||||
|
combinedHulls.Add(hull, new HashSet<Hull>());
|
||||||
|
}
|
||||||
|
|
||||||
|
combinedHulls[hull].Add(linkedHull);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Hull hull in hullList)
|
||||||
|
{
|
||||||
Vector2 relativeHullPos = new Vector2(
|
Vector2 relativeHullPos = new Vector2(
|
||||||
(hull.WorldRect.X - worldBorders.X) / (float)worldBorders.Width,
|
(hull.WorldRect.X - worldBorders.X) / (float)worldBorders.Width,
|
||||||
(worldBorders.Y - hull.WorldRect.Y) / (float)worldBorders.Height);
|
(worldBorders.Y - hull.WorldRect.Y) / (float)worldBorders.Height);
|
||||||
Vector2 relativeHullSize = new Vector2(hull.Rect.Width / (float)worldBorders.Width, hull.Rect.Height / (float)worldBorders.Height);
|
Vector2 relativeHullSize = new Vector2(hull.Rect.Width / (float)worldBorders.Width, hull.Rect.Height / (float)worldBorders.Height);
|
||||||
|
|
||||||
var hullFrame = new GUIFrame(new RectTransform(relativeHullSize, hullContainer.RectTransform) { RelativeOffset = relativeHullPos }, style: "MiniMapRoom", color: Color.DarkCyan * 0.8f)
|
bool hideHull = combinedHulls.ContainsKey(hull) || combinedHulls.Values.Any(hh => hh.Contains(hull));
|
||||||
|
|
||||||
|
if (hideHull) { continue; }
|
||||||
|
|
||||||
|
Color color = Color.DarkCyan * 0.8f;
|
||||||
|
|
||||||
|
var hullFrame = new GUIFrame(new RectTransform(relativeHullSize, hullContainer.RectTransform) { RelativeOffset = relativeHullPos }, style: "MiniMapRoom", color: color)
|
||||||
{
|
{
|
||||||
UserData = hull
|
UserData = hull
|
||||||
};
|
};
|
||||||
new GUIFrame(new RectTransform(Vector2.One, hullFrame.RectTransform), style: "ScanLines", color: Color.DarkCyan * 0.8f);
|
|
||||||
|
new GUIFrame(new RectTransform(Vector2.One, hullFrame.RectTransform), style: "ScanLines", color: color);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var (mainHull, linkedHulls) in combinedHulls)
|
||||||
|
{
|
||||||
|
MiniMapHullData data = ConstructLinkedHulls(mainHull, linkedHulls, hullContainer, worldBorders);
|
||||||
|
|
||||||
|
Vector2 relativeHullPos = new Vector2(
|
||||||
|
(data.Bounds.X - worldBorders.X) / worldBorders.Width,
|
||||||
|
(worldBorders.Y - data.Bounds.Y) / worldBorders.Height);
|
||||||
|
|
||||||
|
Vector2 relativeHullSize = new Vector2(data.Bounds.Width / worldBorders.Width, data.Bounds.Height / worldBorders.Height);
|
||||||
|
|
||||||
|
Color color = Color.DarkCyan * 0.8f;
|
||||||
|
|
||||||
|
float highestY = 0f,
|
||||||
|
highestX = 0f;
|
||||||
|
|
||||||
|
foreach (var (r, _) in data.RectDatas)
|
||||||
|
{
|
||||||
|
float y = r.Y - -r.Height,
|
||||||
|
x = r.X;
|
||||||
|
|
||||||
|
if (y > highestY) { highestY = y; }
|
||||||
|
if (x > highestX) { highestX = x; }
|
||||||
|
}
|
||||||
|
|
||||||
|
HashSet<GUIFrame> frames = new HashSet<GUIFrame>();
|
||||||
|
|
||||||
|
foreach (var (snappredRect, hull) in data.RectDatas)
|
||||||
|
{
|
||||||
|
RectangleF rect = snappredRect;
|
||||||
|
rect.Height = -rect.Height;
|
||||||
|
rect.Y -= rect.Height;
|
||||||
|
|
||||||
|
var (parentW, parentH) = hullContainer.Rect.Size.ToVector2();
|
||||||
|
Vector2 size = new Vector2(rect.Width / parentW, rect.Height / parentH);
|
||||||
|
// TODO this won't be required if we some day switch RectTransform to use RectangleF
|
||||||
|
const float padding = 0.001f;
|
||||||
|
size.X += padding;
|
||||||
|
size.Y += padding;
|
||||||
|
Vector2 pos = new Vector2(rect.X / parentW, rect.Y / parentH);
|
||||||
|
|
||||||
|
GUIFrame hullFrame = new GUIFrame(new RectTransform(size, hullContainer.RectTransform) { RelativeOffset = pos }, style: "ScanLinesSeamless", color: color)
|
||||||
|
{
|
||||||
|
UserData = hull,
|
||||||
|
UVOffset = new Vector2(highestX - rect.X, highestY - rect.Y)
|
||||||
|
};
|
||||||
|
|
||||||
|
frames.Add(hullFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
new GUICustomComponent(new RectTransform(relativeHullSize, hullContainer.RectTransform) { RelativeOffset = relativeHullPos }, (spriteBatch, component) =>
|
||||||
|
{
|
||||||
|
foreach (List<Vector2> list in data.Polygon)
|
||||||
|
{
|
||||||
|
spriteBatch.DrawPolygonInner(hullContainer.Rect.Location.ToVector2(), list, component.Color, 2f);
|
||||||
|
}
|
||||||
|
}, (deltaTime, component) =>
|
||||||
|
{
|
||||||
|
if (component.Parent.Rect.Size != data.ParentSize)
|
||||||
|
{
|
||||||
|
data = ConstructLinkedHulls(mainHull, linkedHulls, hullContainer, worldBorders);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
{
|
||||||
|
UserData = frames,
|
||||||
|
Color = color,
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pointsOfInterest != null)
|
if (pointsOfInterest != null)
|
||||||
@@ -453,6 +557,64 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static MiniMapHullData ConstructLinkedHulls(Hull mainHull, HashSet<Hull> linkedHulls, GUIComponent parent, Rectangle worldBorders)
|
||||||
|
{
|
||||||
|
Rectangle parentRect = parent.Rect;
|
||||||
|
|
||||||
|
Dictionary<Hull, Rectangle> rects = new Dictionary<Hull, Rectangle>();
|
||||||
|
Rectangle worldRect = mainHull.WorldRect;
|
||||||
|
worldRect.Y = -worldRect.Y;
|
||||||
|
|
||||||
|
rects.Add(mainHull, worldRect);
|
||||||
|
|
||||||
|
foreach (Hull hull in linkedHulls)
|
||||||
|
{
|
||||||
|
Rectangle rect = hull.WorldRect;
|
||||||
|
rect.Y = -rect.Y;
|
||||||
|
|
||||||
|
worldRect = Rectangle.Union(worldRect, rect);
|
||||||
|
rects.Add(hull, rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
worldRect.Y = -worldRect.Y;
|
||||||
|
|
||||||
|
List<RectangleF> normalizedRects = new List<RectangleF>();
|
||||||
|
List<Hull> hullRefs = new List<Hull>();
|
||||||
|
foreach (var (hull, rect) in rects)
|
||||||
|
{
|
||||||
|
Rectangle wRect = rect;
|
||||||
|
wRect.Y = -wRect.Y;
|
||||||
|
|
||||||
|
var (posX, posY) = new Vector2(
|
||||||
|
(wRect.X - worldBorders.X) / (float)worldBorders.Width,
|
||||||
|
(worldBorders.Y - wRect.Y) / (float)worldBorders.Height);
|
||||||
|
|
||||||
|
var (scaleX, scaleY) = new Vector2(wRect.Width / (float)worldBorders.Width, wRect.Height / (float)worldBorders.Height);
|
||||||
|
|
||||||
|
RectangleF newRect = new RectangleF(posX * parentRect.Width, posY * parentRect.Height, scaleX * parentRect.Width, scaleY * parentRect.Height);
|
||||||
|
|
||||||
|
normalizedRects.Add(newRect);
|
||||||
|
hullRefs.Add(hull);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImmutableArray<RectangleF> snappedRectangles = ToolBox.SnapRectangles(normalizedRects, treshold: 1);
|
||||||
|
|
||||||
|
List<List<Vector2>> polygon = ToolBox.CombineRectanglesIntoShape(snappedRectangles);
|
||||||
|
|
||||||
|
List<List<Vector2>> scaledPolygon = new List<List<Vector2>>();
|
||||||
|
|
||||||
|
foreach (List<Vector2> list in polygon)
|
||||||
|
{
|
||||||
|
var (polySizeX, polySizeY) = ToolBox.GetPolygonBoundingBoxSize(list);
|
||||||
|
float sizeX = polySizeX - 1f,
|
||||||
|
sizeY = polySizeY - 1f;
|
||||||
|
|
||||||
|
scaledPolygon.Add(ToolBox.ScalePolygon(list, new Vector2(sizeX / polySizeX, sizeY / polySizeY)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new MiniMapHullData(scaledPolygon, worldRect, parentRect.Size, snappedRectangles, hullRefs.ToImmutableArray());
|
||||||
|
}
|
||||||
|
|
||||||
public void CheckForErrors()
|
public void CheckForErrors()
|
||||||
{
|
{
|
||||||
List<string> errorMsgs = new List<string>();
|
List<string> errorMsgs = new List<string>();
|
||||||
|
|||||||
@@ -64,7 +64,10 @@ namespace Barotrauma.Networking
|
|||||||
string orderOption = orderMessageInfo.OrderOption;
|
string orderOption = orderMessageInfo.OrderOption;
|
||||||
orderOption ??= orderMessageInfo.OrderOptionIndex.HasValue && orderMessageInfo.OrderOptionIndex >= 0 && orderMessageInfo.OrderOptionIndex < orderPrefab.Options.Length ?
|
orderOption ??= orderMessageInfo.OrderOptionIndex.HasValue && orderMessageInfo.OrderOptionIndex >= 0 && orderMessageInfo.OrderOptionIndex < orderPrefab.Options.Length ?
|
||||||
orderPrefab.Options[orderMessageInfo.OrderOptionIndex.Value] : "";
|
orderPrefab.Options[orderMessageInfo.OrderOptionIndex.Value] : "";
|
||||||
txt = orderPrefab.GetChatMessage(orderMessageInfo.TargetCharacter?.Name, senderCharacter?.CurrentHull?.DisplayName, givingOrderToSelf: orderMessageInfo.TargetCharacter == senderCharacter, orderOption: orderOption);
|
txt = orderPrefab.GetChatMessage(orderMessageInfo.TargetCharacter?.Name, senderCharacter?.CurrentHull?.DisplayName,
|
||||||
|
givingOrderToSelf: orderMessageInfo.TargetCharacter == senderCharacter,
|
||||||
|
orderOption: orderOption,
|
||||||
|
priority: orderMessageInfo.Priority);
|
||||||
|
|
||||||
if (GameMain.Client.GameStarted && Screen.Selected == GameMain.GameScreen)
|
if (GameMain.Client.GameStarted && Screen.Selected == GameMain.GameScreen)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -550,6 +550,13 @@ namespace Barotrauma.Networking
|
|||||||
okButton.OnClicked += msgBox.Close;
|
okButton.OnClicked += msgBox.Close;
|
||||||
var cancelButton = msgBox.Buttons[1];
|
var cancelButton = msgBox.Buttons[1];
|
||||||
cancelButton.OnClicked += msgBox.Close;
|
cancelButton.OnClicked += msgBox.Close;
|
||||||
|
passwordBox.OnEnterPressed += (GUITextBox textBox, string text) =>
|
||||||
|
{
|
||||||
|
msgBox.Close();
|
||||||
|
clientPeer?.SendPassword(passwordBox.Text);
|
||||||
|
requiresPw = false;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
okButton.OnClicked += (GUIButton button, object obj) =>
|
okButton.OnClicked += (GUIButton button, object obj) =>
|
||||||
{
|
{
|
||||||
@@ -565,6 +572,8 @@ namespace Barotrauma.Networking
|
|||||||
GameMain.ServerListScreen.Select();
|
GameMain.ServerListScreen.Select();
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
yield return CoroutineStatus.Running;
|
||||||
|
passwordBox.Select();
|
||||||
|
|
||||||
while (GUIMessageBox.MessageBoxes.Contains(msgBox))
|
while (GUIMessageBox.MessageBoxes.Contains(msgBox))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -110,12 +110,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
if (frame == null) { return; }
|
if (frame == null) { return; }
|
||||||
|
|
||||||
var previewContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.98f), frame.RectTransform, Anchor.Center))
|
var title = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), frame.RectTransform), ServerName, font: GUI.LargeFont)
|
||||||
{
|
|
||||||
Stretch = true
|
|
||||||
};
|
|
||||||
|
|
||||||
var title = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), previewContainer.RectTransform, Anchor.CenterLeft), ServerName, font: GUI.LargeFont)
|
|
||||||
{
|
{
|
||||||
ToolTip = ServerName
|
ToolTip = ServerName
|
||||||
};
|
};
|
||||||
@@ -141,41 +136,30 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), previewContainer.RectTransform),
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), frame.RectTransform),
|
||||||
TextManager.AddPunctuation(':', TextManager.Get("ServerListVersion"), string.IsNullOrEmpty(GameVersion) ? TextManager.Get("Unknown") : GameVersion));
|
TextManager.AddPunctuation(':', TextManager.Get("ServerListVersion"), string.IsNullOrEmpty(GameVersion) ? TextManager.Get("Unknown") : GameVersion));
|
||||||
|
|
||||||
bool hidePlaystyleBanner = previewContainer.Rect.Height < 380 || !PlayStyle.HasValue;
|
bool hidePlaystyleBanner = !PlayStyle.HasValue;
|
||||||
if (!hidePlaystyleBanner)
|
if (!hidePlaystyleBanner)
|
||||||
{
|
{
|
||||||
PlayStyle playStyle = PlayStyle ?? Networking.PlayStyle.Serious;
|
PlayStyle playStyle = PlayStyle ?? Networking.PlayStyle.Serious;
|
||||||
Sprite playStyleBannerSprite = ServerListScreen.PlayStyleBanners[(int)playStyle];
|
Sprite playStyleBannerSprite = ServerListScreen.PlayStyleBanners[(int)playStyle];
|
||||||
float playStyleBannerAspectRatio = playStyleBannerSprite.SourceRect.Width / playStyleBannerSprite.SourceRect.Height;
|
float playStyleBannerAspectRatio = playStyleBannerSprite.SourceRect.Width / playStyleBannerSprite.SourceRect.Height;
|
||||||
var playStyleBanner = new GUIImage(new RectTransform(new Point(previewContainer.Rect.Width, (int)(previewContainer.Rect.Width / playStyleBannerAspectRatio)), previewContainer.RectTransform),
|
var playStyleBanner = new GUIImage(new RectTransform(new Point(frame.Rect.Width, (int)(frame.Rect.Width / playStyleBannerAspectRatio)), frame.RectTransform),
|
||||||
playStyleBannerSprite, null, true);
|
playStyleBannerSprite, null, true);
|
||||||
|
|
||||||
var playStyleName = new GUITextBlock(new RectTransform(new Vector2(0.15f, 0.0f), playStyleBanner.RectTransform) { RelativeOffset = new Vector2(0.01f, 0.06f) },
|
var playStyleName = new GUITextBlock(new RectTransform(new Vector2(0.15f, 0.0f), playStyleBanner.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.06f) },
|
||||||
TextManager.AddPunctuation(':', TextManager.Get("serverplaystyle"), TextManager.Get("servertag."+ playStyle)), textColor: Color.White,
|
TextManager.AddPunctuation(':', TextManager.Get("serverplaystyle"), TextManager.Get("servertag."+ playStyle)), textColor: Color.White,
|
||||||
font: GUI.SmallFont, textAlignment: Alignment.Center,
|
font: GUI.SmallFont, textAlignment: Alignment.Center,
|
||||||
color: ServerListScreen.PlayStyleColors[(int)playStyle], style: "GUISlopedHeader");
|
color: ServerListScreen.PlayStyleColors[(int)playStyle], style: "GUISlopedHeader");
|
||||||
playStyleName.RectTransform.NonScaledSize = (playStyleName.Font.MeasureString(playStyleName.Text) + new Vector2(20, 5) * GUI.Scale).ToPoint();
|
playStyleName.RectTransform.NonScaledSize = (playStyleName.Font.MeasureString(playStyleName.Text) + new Vector2(20, 5) * GUI.Scale).ToPoint();
|
||||||
playStyleName.RectTransform.IsFixedSize = true;
|
playStyleName.RectTransform.IsFixedSize = true;
|
||||||
|
|
||||||
var serverTypeContainer = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.2f), playStyleBanner.RectTransform, Anchor.BottomLeft, Pivot.BottomLeft),
|
|
||||||
"MainMenuNotifBackground", Color.Black)
|
|
||||||
{
|
|
||||||
CanBeFocused = false,
|
|
||||||
};
|
|
||||||
|
|
||||||
var serverType = new GUITextBlock(new RectTransform(Vector2.One, serverTypeContainer.RectTransform, Anchor.CenterLeft),
|
|
||||||
TextManager.Get((OwnerID != 0 || LobbyID != 0) ? "SteamP2PServer" : "DedicatedServer"), textAlignment: Alignment.CenterLeft);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var serverType = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), previewContainer.RectTransform, Anchor.CenterLeft),
|
|
||||||
TextManager.Get((OwnerID != 0 || LobbyID != 0) ? "SteamP2PServer" : "DedicatedServer"), textAlignment: Alignment.CenterLeft);
|
|
||||||
}
|
}
|
||||||
|
var serverType = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), frame.RectTransform),
|
||||||
|
TextManager.Get((OwnerID != 0 || LobbyID != 0) ? "SteamP2PServer" : "DedicatedServer"), textAlignment: Alignment.TopLeft);
|
||||||
|
serverType.RectTransform.MinSize = new Point(0, (int)(serverType.Rect.Height * 1.5f));
|
||||||
|
|
||||||
var content = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.6f), previewContainer.RectTransform))
|
var content = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.6f), frame.RectTransform))
|
||||||
{
|
{
|
||||||
Stretch = true
|
Stretch = true
|
||||||
};
|
};
|
||||||
@@ -285,7 +269,6 @@ namespace Barotrauma.Networking
|
|||||||
else
|
else
|
||||||
usingWhiteList.Selected = UsingWhiteList.Value;
|
usingWhiteList.Selected = UsingWhiteList.Value;
|
||||||
|
|
||||||
|
|
||||||
content.RectTransform.SizeChanged += () =>
|
content.RectTransform.SizeChanged += () =>
|
||||||
{
|
{
|
||||||
GUITextBlock.AutoScaleAndNormalize(allowSpectating.TextBlock, allowRespawn.TextBlock, usingWhiteList.TextBlock);
|
GUITextBlock.AutoScaleAndNormalize(allowSpectating.TextBlock, allowRespawn.TextBlock, usingWhiteList.TextBlock);
|
||||||
@@ -294,7 +277,7 @@ namespace Barotrauma.Networking
|
|||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform),
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform),
|
||||||
TextManager.Get("ServerListContentPackages"), textAlignment: Alignment.Center, font: GUI.SubHeadingFont);
|
TextManager.Get("ServerListContentPackages"), textAlignment: Alignment.Center, font: GUI.SubHeadingFont);
|
||||||
|
|
||||||
var contentPackageList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.2f), content.RectTransform)) { ScrollBarVisible = true };
|
var contentPackageList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.3f), frame.RectTransform)) { ScrollBarVisible = true };
|
||||||
if (ContentPackageNames.Count == 0)
|
if (ContentPackageNames.Count == 0)
|
||||||
{
|
{
|
||||||
new GUITextBlock(new RectTransform(Vector2.One, contentPackageList.Content.RectTransform), TextManager.Get("Unknown"), textAlignment: Alignment.Center)
|
new GUITextBlock(new RectTransform(Vector2.One, contentPackageList.Content.RectTransform), TextManager.Get("Unknown"), textAlignment: Alignment.Center)
|
||||||
@@ -309,7 +292,7 @@ namespace Barotrauma.Networking
|
|||||||
var packageText = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.15f), contentPackageList.Content.RectTransform) { MinSize = new Point(0, 15) },
|
var packageText = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.15f), contentPackageList.Content.RectTransform) { MinSize = new Point(0, 15) },
|
||||||
ContentPackageNames[i])
|
ContentPackageNames[i])
|
||||||
{
|
{
|
||||||
Enabled = false
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
if (i < ContentPackageHashes.Count)
|
if (i < ContentPackageHashes.Count)
|
||||||
{
|
{
|
||||||
@@ -322,7 +305,7 @@ namespace Barotrauma.Networking
|
|||||||
//workshop download link found
|
//workshop download link found
|
||||||
if (i < ContentPackageWorkshopIds.Count && ContentPackageWorkshopIds[i] != 0)
|
if (i < ContentPackageWorkshopIds.Count && ContentPackageWorkshopIds[i] != 0)
|
||||||
{
|
{
|
||||||
packageText.TextColor = Color.Yellow;
|
packageText.TextColor = GUI.Style.Yellow;
|
||||||
packageText.ToolTip = TextManager.GetWithVariable("ServerListIncompatibleContentPackageWorkshopAvailable", "[contentpackage]", ContentPackageNames[i]);
|
packageText.ToolTip = TextManager.GetWithVariable("ServerListIncompatibleContentPackageWorkshopAvailable", "[contentpackage]", ContentPackageNames[i]);
|
||||||
}
|
}
|
||||||
else //no package or workshop download link found, tough luck
|
else //no package or workshop download link found, tough luck
|
||||||
|
|||||||
@@ -1207,7 +1207,7 @@ namespace Barotrauma.Steam
|
|||||||
foreach (string file in allPackageFiles)
|
foreach (string file in allPackageFiles)
|
||||||
{
|
{
|
||||||
if (file == metaDataFilePath) { continue; }
|
if (file == metaDataFilePath) { continue; }
|
||||||
string relativePath = UpdaterUtil.GetRelativePath(file, item.Directory);
|
string relativePath = Path.GetRelativePath(item.Directory, file);
|
||||||
string fullPath = Path.GetFullPath(relativePath);
|
string fullPath = Path.GetFullPath(relativePath);
|
||||||
if (contentPackage.Files.Any(f => { string fp = Path.GetFullPath(f.Path); return fp == fullPath; })) { continue; }
|
if (contentPackage.Files.Any(f => { string fp = Path.GetFullPath(f.Path); return fp == fullPath; })) { continue; }
|
||||||
nonContentFiles.Add(relativePath);
|
nonContentFiles.Add(relativePath);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Microsoft.Xna.Framework;
|
|||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection.Metadata;
|
|
||||||
|
|
||||||
namespace Barotrauma.Particles
|
namespace Barotrauma.Particles
|
||||||
{
|
{
|
||||||
@@ -16,6 +15,8 @@ namespace Barotrauma.Particles
|
|||||||
public delegate void OnChangeHullHandler(Vector2 position, Hull currentHull);
|
public delegate void OnChangeHullHandler(Vector2 position, Hull currentHull);
|
||||||
public OnChangeHullHandler OnChangeHull;
|
public OnChangeHullHandler OnChangeHull;
|
||||||
|
|
||||||
|
public OnChangeHullHandler OnCollision;
|
||||||
|
|
||||||
private Vector2 position;
|
private Vector2 position;
|
||||||
private Vector2 prevPosition;
|
private Vector2 prevPosition;
|
||||||
|
|
||||||
@@ -166,6 +167,7 @@ namespace Barotrauma.Particles
|
|||||||
HighQualityCollisionDetection = false;
|
HighQualityCollisionDetection = false;
|
||||||
|
|
||||||
OnChangeHull = null;
|
OnChangeHull = null;
|
||||||
|
OnCollision = null;
|
||||||
|
|
||||||
subEmitters.Clear();
|
subEmitters.Clear();
|
||||||
hasSubEmitters = false;
|
hasSubEmitters = false;
|
||||||
@@ -340,12 +342,20 @@ namespace Barotrauma.Particles
|
|||||||
Vector2 collisionNormal = Vector2.Zero;
|
Vector2 collisionNormal = Vector2.Zero;
|
||||||
if (velocity.Y < 0.0f && position.Y - prefab.CollisionRadius * size.Y < hullRect.Y - hullRect.Height)
|
if (velocity.Y < 0.0f && position.Y - prefab.CollisionRadius * size.Y < hullRect.Y - hullRect.Height)
|
||||||
{
|
{
|
||||||
if (prefab.DeleteOnCollision) { return UpdateResult.Delete; }
|
if (prefab.DeleteOnCollision)
|
||||||
|
{
|
||||||
|
OnCollision?.Invoke(position, currentHull);
|
||||||
|
return UpdateResult.Delete;
|
||||||
|
}
|
||||||
collisionNormal = new Vector2(0.0f, 1.0f);
|
collisionNormal = new Vector2(0.0f, 1.0f);
|
||||||
}
|
}
|
||||||
else if (velocity.Y > 0.0f && position.Y + prefab.CollisionRadius * size.Y > hullRect.Y)
|
else if (velocity.Y > 0.0f && position.Y + prefab.CollisionRadius * size.Y > hullRect.Y)
|
||||||
{
|
{
|
||||||
if (prefab.DeleteOnCollision) { return UpdateResult.Delete; }
|
if (prefab.DeleteOnCollision)
|
||||||
|
{
|
||||||
|
OnCollision?.Invoke(position, currentHull);
|
||||||
|
return UpdateResult.Delete;
|
||||||
|
}
|
||||||
collisionNormal = new Vector2(0.0f, -1.0f);
|
collisionNormal = new Vector2(0.0f, -1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -487,6 +497,8 @@ namespace Barotrauma.Particles
|
|||||||
velocity.Y = Math.Sign(collisionNormal.Y) * Math.Abs(velocity.Y) * prefab.Restitution;
|
velocity.Y = Math.Sign(collisionNormal.Y) * Math.Abs(velocity.Y) * prefab.Restitution;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OnCollision?.Invoke(position, currentHull);
|
||||||
|
|
||||||
velocity += subVel;
|
velocity += subVel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,6 +535,8 @@ namespace Barotrauma.Particles
|
|||||||
velocity.Y *= (1.0f - prefab.Friction);
|
velocity.Y *= (1.0f - prefab.Friction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OnCollision?.Invoke(position, currentHull);
|
||||||
|
|
||||||
velocity *= prefab.Restitution;
|
velocity *= prefab.Restitution;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -138,6 +138,8 @@ namespace Barotrauma.Particles
|
|||||||
|
|
||||||
public void Emit(float deltaTime, Vector2 position, Hull hullGuess = null, float angle = 0.0f, float particleRotation = 0.0f, float velocityMultiplier = 1.0f, float sizeMultiplier = 1.0f, float amountMultiplier = 1.0f, Color? colorMultiplier = null, ParticlePrefab overrideParticle = null, Tuple<Vector2, Vector2> tracerPoints = null)
|
public void Emit(float deltaTime, Vector2 position, Hull hullGuess = null, float angle = 0.0f, float particleRotation = 0.0f, float velocityMultiplier = 1.0f, float sizeMultiplier = 1.0f, float amountMultiplier = 1.0f, Color? colorMultiplier = null, ParticlePrefab overrideParticle = null, Tuple<Vector2, Vector2> tracerPoints = null)
|
||||||
{
|
{
|
||||||
|
if (GameMain.Client?.MidRoundSyncing ?? false) { return; }
|
||||||
|
|
||||||
if (initialDelay < Prefab.Properties.InitialDelay)
|
if (initialDelay < Prefab.Properties.InitialDelay)
|
||||||
{
|
{
|
||||||
initialDelay += deltaTime;
|
initialDelay += deltaTime;
|
||||||
|
|||||||
@@ -133,22 +133,41 @@ namespace Barotrauma.Particles
|
|||||||
|
|
||||||
public Particle CreateParticle(ParticlePrefab prefab, Vector2 position, Vector2 velocity, float rotation = 0.0f, Hull hullGuess = null, bool drawOnTop = false, float collisionIgnoreTimer = 0f, Tuple<Vector2, Vector2> tracerPoints = null)
|
public Particle CreateParticle(ParticlePrefab prefab, Vector2 position, Vector2 velocity, float rotation = 0.0f, Hull hullGuess = null, bool drawOnTop = false, float collisionIgnoreTimer = 0f, Tuple<Vector2, Vector2> tracerPoints = null)
|
||||||
{
|
{
|
||||||
if (particleCount >= MaxParticles || prefab == null || prefab.Sprites.Count == 0) { return null; }
|
if (prefab == null || prefab.Sprites.Count == 0) { return null; }
|
||||||
|
|
||||||
// this should be optimized for tracers after prototyping
|
if (particleCount >= MaxParticles)
|
||||||
if (tracerPoints == null)
|
|
||||||
{
|
{
|
||||||
Vector2 particleEndPos = prefab.CalculateEndPosition(position, velocity);
|
for (int i = 0; i < particleCount; i++)
|
||||||
|
{
|
||||||
Vector2 minPos = new Vector2(Math.Min(position.X, particleEndPos.X), Math.Min(position.Y, particleEndPos.Y));
|
if (particles[i].Prefab.Priority < prefab.Priority)
|
||||||
Vector2 maxPos = new Vector2(Math.Max(position.X, particleEndPos.X), Math.Max(position.Y, particleEndPos.Y));
|
{
|
||||||
|
RemoveParticle(i);
|
||||||
Rectangle expandedViewRect = MathUtils.ExpandRect(cam.WorldView, MaxOutOfViewDist);
|
break;
|
||||||
|
}
|
||||||
if (minPos.X > expandedViewRect.Right || maxPos.X < expandedViewRect.X) { return null; }
|
}
|
||||||
if (minPos.Y > expandedViewRect.Y || maxPos.Y < expandedViewRect.Y - expandedViewRect.Height) { return null; }
|
if (particleCount >= MaxParticles) { return null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector2 particleEndPos = prefab.CalculateEndPosition(position, velocity);
|
||||||
|
|
||||||
|
Vector2 minPos = new Vector2(Math.Min(position.X, particleEndPos.X), Math.Min(position.Y, particleEndPos.Y));
|
||||||
|
Vector2 maxPos = new Vector2(Math.Max(position.X, particleEndPos.X), Math.Max(position.Y, particleEndPos.Y));
|
||||||
|
|
||||||
|
if (tracerPoints != null)
|
||||||
|
{
|
||||||
|
minPos = new Vector2(
|
||||||
|
Math.Min(Math.Min(minPos.X, tracerPoints.Item1.X), tracerPoints.Item2.X),
|
||||||
|
Math.Min(Math.Min(minPos.Y, tracerPoints.Item1.Y), tracerPoints.Item2.Y));
|
||||||
|
maxPos = new Vector2(
|
||||||
|
Math.Max(Math.Max(maxPos.X, tracerPoints.Item1.X), tracerPoints.Item2.X),
|
||||||
|
Math.Max(Math.Max(maxPos.Y, tracerPoints.Item1.Y), tracerPoints.Item2.Y));
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle expandedViewRect = MathUtils.ExpandRect(cam.WorldView, MaxOutOfViewDist);
|
||||||
|
|
||||||
|
if (minPos.X > expandedViewRect.Right || maxPos.X < expandedViewRect.X) { return null; }
|
||||||
|
if (minPos.Y > expandedViewRect.Y || maxPos.Y < expandedViewRect.Y - expandedViewRect.Height) { return null; }
|
||||||
|
|
||||||
if (particles[particleCount] == null) particles[particleCount] = new Particle();
|
if (particles[particleCount] == null) particles[particleCount] = new Particle();
|
||||||
|
|
||||||
particles[particleCount].Init(prefab, position, velocity, rotation, hullGuess, drawOnTop, collisionIgnoreTimer, tracerPoints: tracerPoints);
|
particles[particleCount].Init(prefab, position, velocity, rotation, hullGuess, drawOnTop, collisionIgnoreTimer, tracerPoints: tracerPoints);
|
||||||
|
|||||||
@@ -180,16 +180,13 @@ namespace Barotrauma.Particles
|
|||||||
[Editable, Serialize("1.0,1.0", false, description: "The maximum initial size of the particle.")]
|
[Editable, Serialize("1.0,1.0", false, description: "The maximum initial size of the particle.")]
|
||||||
public Vector2 StartSizeMax { get; private set; }
|
public Vector2 StartSizeMax { get; private set; }
|
||||||
|
|
||||||
[Editable]
|
[Editable, Serialize("0.0,0.0", false, description: "How much the size of the particle changes per second. The rate of growth for each particle is randomize between SizeChangeMin and SizeChangeMax.")]
|
||||||
[Serialize("0.0,0.0", false, description: "How much the size of the particle changes per second. The rate of growth for each particle is randomize between SizeChangeMin and SizeChangeMax.")]
|
|
||||||
public Vector2 SizeChangeMin { get; private set; }
|
public Vector2 SizeChangeMin { get; private set; }
|
||||||
|
|
||||||
[Editable]
|
[Editable, Serialize("0.0,0.0", false, description: "How much the size of the particle changes per second. The rate of growth for each particle is randomize between SizeChangeMin and SizeChangeMax.")]
|
||||||
[Serialize("0.0,0.0", false, description: "How much the size of the particle changes per second. The rate of growth for each particle is randomize between SizeChangeMin and SizeChangeMax.")]
|
|
||||||
public Vector2 SizeChangeMax { get; private set; }
|
public Vector2 SizeChangeMax { get; private set; }
|
||||||
|
|
||||||
[Editable]
|
[Editable, Serialize(0.0f, false, description: "How many seconds it takes for the particle to grow to it's initial size.")]
|
||||||
[Serialize(0.0f, false, description: "How many seconds it takes for the particle to grow to it's initial size.")]
|
|
||||||
public float GrowTime { get; private set; }
|
public float GrowTime { get; private set; }
|
||||||
|
|
||||||
//rendering -----------------------------------------
|
//rendering -----------------------------------------
|
||||||
@@ -215,6 +212,9 @@ namespace Barotrauma.Particles
|
|||||||
[Editable, Serialize(ParticleBlendState.AlphaBlend, false, description: "The type of blending to use when rendering the particle.")]
|
[Editable, Serialize(ParticleBlendState.AlphaBlend, false, description: "The type of blending to use when rendering the particle.")]
|
||||||
public ParticleBlendState BlendState { get; private set; }
|
public ParticleBlendState BlendState { get; private set; }
|
||||||
|
|
||||||
|
[Editable, Serialize(0, false, description: "Particles with a higher priority can replace lower-priority ones if the maximum number of active particles has been reached.")]
|
||||||
|
public int Priority { get; private set; }
|
||||||
|
|
||||||
//animation -----------------------------------------
|
//animation -----------------------------------------
|
||||||
|
|
||||||
[Editable(0.0f, float.MaxValue), Serialize(1.0f, false, description: "The duration of the particle's animation cycle (if it's animated).")]
|
[Editable(0.0f, float.MaxValue), Serialize(1.0f, false, description: "The duration of the particle's animation cycle (if it's animated).")]
|
||||||
|
|||||||
@@ -54,9 +54,11 @@ namespace Barotrauma
|
|||||||
executableDir = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
|
executableDir = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
|
||||||
Directory.SetCurrentDirectory(executableDir);
|
Directory.SetCurrentDirectory(executableDir);
|
||||||
SteamManager.Initialize();
|
SteamManager.Initialize();
|
||||||
|
EnableNvOptimus();
|
||||||
Game = new GameMain(args);
|
Game = new GameMain(args);
|
||||||
Game.Run();
|
Game.Run();
|
||||||
Game.Dispose();
|
Game.Dispose();
|
||||||
|
FreeNvOptimus();
|
||||||
|
|
||||||
CrossThread.ProcessTasks();
|
CrossThread.ProcessTasks();
|
||||||
}
|
}
|
||||||
@@ -263,6 +265,27 @@ namespace Barotrauma
|
|||||||
" if you'd like to help fix this bug, you may post it on Barotrauma's GitHub issue tracker: https://github.com/Regalis11/Barotrauma/issues/", filePath);
|
" if you'd like to help fix this bug, you may post it on Barotrauma's GitHub issue tracker: https://github.com/Regalis11/Barotrauma/issues/", filePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private static IntPtr nvApi64Dll = IntPtr.Zero;
|
||||||
|
private static void EnableNvOptimus()
|
||||||
|
{
|
||||||
|
#if WINDOWS && X64
|
||||||
|
// We force load nvapi64.dll so nvidia gives us the dedicated GPU on optimus laptops.
|
||||||
|
// This is not a method for getting optimus that is documented by nvidia, but it works, so...
|
||||||
|
if (NativeLibrary.TryLoad("nvapi64.dll", out nvApi64Dll))
|
||||||
|
{
|
||||||
|
DebugConsole.Log("Loaded nvapi64.dll successfully");
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void FreeNvOptimus()
|
||||||
|
{
|
||||||
|
#warning TODO: determine if we can do this safely
|
||||||
|
//NativeLibrary.Free(nvApi64Dll);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -466,7 +466,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
var sub = child.UserData as SubmarineInfo;
|
var sub = child.UserData as SubmarineInfo;
|
||||||
if (sub == null) { return; }
|
if (sub == null) { return; }
|
||||||
child.Visible = string.IsNullOrEmpty(filter) ? true : sub.DisplayName.ToLower().Contains(filter.ToLower());
|
child.Visible = string.IsNullOrEmpty(filter) || sub.DisplayName.ToLower().Contains(filter.ToLower());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -628,7 +628,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
TextGetter = () =>
|
TextGetter = () =>
|
||||||
{
|
{
|
||||||
return TextManager.AddPunctuation(':', TextManager.Get("Missions"), $"{Campaign.NumberOfMissionsAtLocation(destination)}/{Campaign.Settings.MaxMissionCount}");
|
return TextManager.AddPunctuation(':', TextManager.Get("Missions"), $"{Campaign.NumberOfMissionsAtLocation(destination)}/{Campaign.Settings.TotalMaxMissionCount}");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -735,7 +735,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private void UpdateMaxMissions(Location location)
|
private void UpdateMaxMissions(Location location)
|
||||||
{
|
{
|
||||||
hasMaxMissions = Campaign.NumberOfMissionsAtLocation(location) >= Campaign.Settings.MaxMissionCount;
|
hasMaxMissions = Campaign.NumberOfMissionsAtLocation(location) >= Campaign.Settings.TotalMaxMissionCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ namespace Barotrauma.CharacterEditor
|
|||||||
{
|
{
|
||||||
FileSelection.OnFileSelected = (file) =>
|
FileSelection.OnFileSelected = (file) =>
|
||||||
{
|
{
|
||||||
string relativePath = UpdaterUtil.GetRelativePath(Path.GetFullPath(file), Environment.CurrentDirectory);
|
string relativePath = Path.GetRelativePath(Environment.CurrentDirectory, Path.GetFullPath(file));
|
||||||
string destinationPath = relativePath;
|
string destinationPath = relativePath;
|
||||||
|
|
||||||
//copy file to XML path if it's not located relative to the game's files
|
//copy file to XML path if it's not located relative to the game's files
|
||||||
|
|||||||
@@ -541,7 +541,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private XElement? ExportXML()
|
private XElement? ExportXML()
|
||||||
{
|
{
|
||||||
XElement mainElement = new XElement("ScriptedEvent", new XAttribute("identifier", projectName.RemoveWhitespace().ToLower()));
|
XElement mainElement = new XElement("ScriptedEvent", new XAttribute("identifier", projectName.RemoveWhitespace().ToLowerInvariant()));
|
||||||
EditorNode? startNode = null;
|
EditorNode? startNode = null;
|
||||||
foreach (EditorNode eventNode in nodeList.Where(node => node is EventNode || node is SpecialNode))
|
foreach (EditorNode eventNode in nodeList.Where(node => node is EventNode || node is SpecialNode))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ namespace Barotrauma
|
|||||||
public Effect PostProcessEffect { get; private set; }
|
public Effect PostProcessEffect { get; private set; }
|
||||||
public Effect GradientEffect { get; private set; }
|
public Effect GradientEffect { get; private set; }
|
||||||
public Effect GrainEffect { get; private set; }
|
public Effect GrainEffect { get; private set; }
|
||||||
|
public Effect BlueprintEffect { get; set; }
|
||||||
|
|
||||||
public GameScreen(GraphicsDevice graphics, ContentManager content)
|
public GameScreen(GraphicsDevice graphics, ContentManager content)
|
||||||
{
|
{
|
||||||
@@ -43,12 +44,14 @@ namespace Barotrauma
|
|||||||
PostProcessEffect = content.Load<Effect>("Effects/postprocess_opengl");
|
PostProcessEffect = content.Load<Effect>("Effects/postprocess_opengl");
|
||||||
GradientEffect = content.Load<Effect>("Effects/gradientshader_opengl");
|
GradientEffect = content.Load<Effect>("Effects/gradientshader_opengl");
|
||||||
GrainEffect = content.Load<Effect>("Effects/grainshader_opengl");
|
GrainEffect = content.Load<Effect>("Effects/grainshader_opengl");
|
||||||
|
BlueprintEffect = content.Load<Effect>("Effects/blueprintshader_opengl");
|
||||||
#else
|
#else
|
||||||
//var blurEffect = content.Load<Effect>("Effects/blurshader");
|
//var blurEffect = content.Load<Effect>("Effects/blurshader");
|
||||||
damageEffect = content.Load<Effect>("Effects/damageshader");
|
damageEffect = content.Load<Effect>("Effects/damageshader");
|
||||||
PostProcessEffect = content.Load<Effect>("Effects/postprocess");
|
PostProcessEffect = content.Load<Effect>("Effects/postprocess");
|
||||||
GradientEffect = content.Load<Effect>("Effects/gradientshader");
|
GradientEffect = content.Load<Effect>("Effects/gradientshader");
|
||||||
GrainEffect = content.Load<Effect>("Effects/grainshader");
|
GrainEffect = content.Load<Effect>("Effects/grainshader");
|
||||||
|
BlueprintEffect = content.Load<Effect>("Effects/blueprintshader");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
damageStencil = TextureLoader.FromFile("Content/Map/walldamage.png");
|
damageStencil = TextureLoader.FromFile("Content/Map/walldamage.png");
|
||||||
|
|||||||
@@ -2021,6 +2021,7 @@ namespace Barotrauma
|
|||||||
if (playerFrame == null) { return; }
|
if (playerFrame == null) { return; }
|
||||||
playerFrame.Text = client.Name;
|
playerFrame.Text = client.Name;
|
||||||
|
|
||||||
|
playerFrame.ToolTip = "";
|
||||||
Color color = Color.White;
|
Color color = Color.White;
|
||||||
if (SelectedMode == GameModePreset.PvP)
|
if (SelectedMode == GameModePreset.PvP)
|
||||||
{
|
{
|
||||||
@@ -2028,15 +2029,28 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
case CharacterTeamType.Team1:
|
case CharacterTeamType.Team1:
|
||||||
color = new Color(0, 110, 150, 255);
|
color = new Color(0, 110, 150, 255);
|
||||||
|
playerFrame.ToolTip = TextManager.GetWithVariable("teampreference", "[team]", TextManager.Get("teampreference.team1"));
|
||||||
break;
|
break;
|
||||||
case CharacterTeamType.Team2:
|
case CharacterTeamType.Team2:
|
||||||
color = new Color(150, 110, 0, 255);
|
color = new Color(150, 110, 0, 255);
|
||||||
|
playerFrame.ToolTip = TextManager.GetWithVariable("teampreference", "[team]", TextManager.Get("teampreference.team2"));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
playerFrame.ToolTip = TextManager.GetWithVariable("teampreference", "[team]", TextManager.Get("none"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (JobPrefab.Prefabs.ContainsKey(client.PreferredJob))
|
else
|
||||||
{
|
{
|
||||||
color = JobPrefab.Prefabs[client.PreferredJob].UIColor;
|
if (JobPrefab.Prefabs.ContainsKey(client.PreferredJob))
|
||||||
|
{
|
||||||
|
color = JobPrefab.Prefabs[client.PreferredJob].UIColor;
|
||||||
|
playerFrame.ToolTip = TextManager.GetWithVariable("jobpreference", "[job]", JobPrefab.Prefabs[client.PreferredJob].Name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
playerFrame.ToolTip = TextManager.GetWithVariable("jobpreference", "[job]", TextManager.Get("none"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
playerFrame.Color = color * 0.4f;
|
playerFrame.Color = color * 0.4f;
|
||||||
playerFrame.HoverColor = color * 0.6f;
|
playerFrame.HoverColor = color * 0.6f;
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ namespace Barotrauma
|
|||||||
private GUIFrame menu;
|
private GUIFrame menu;
|
||||||
|
|
||||||
private GUIListBox serverList;
|
private GUIListBox serverList;
|
||||||
private GUIFrame serverPreview;
|
private GUIFrame serverPreviewContainer;
|
||||||
|
private GUIListBox serverPreview;
|
||||||
|
|
||||||
private GUIButton joinButton;
|
private GUIButton joinButton;
|
||||||
private ServerInfo selectedServer;
|
private ServerInfo selectedServer;
|
||||||
@@ -340,11 +341,11 @@ namespace Barotrauma
|
|||||||
void RecalculateHolder()
|
void RecalculateHolder()
|
||||||
{
|
{
|
||||||
float listContainerSubtract = filtersHolder.Visible ? sidebarWidth : 0.0f;
|
float listContainerSubtract = filtersHolder.Visible ? sidebarWidth : 0.0f;
|
||||||
listContainerSubtract += serverPreview.Visible ? sidebarWidth : 0.0f;
|
listContainerSubtract += serverPreviewContainer.Visible ? sidebarWidth : 0.0f;
|
||||||
|
|
||||||
float toggleButtonsSubtract = 1.1f * filterToggle.Rect.Width / serverListHolder.Rect.Width;
|
float toggleButtonsSubtract = 1.1f * filterToggle.Rect.Width / serverListHolder.Rect.Width;
|
||||||
listContainerSubtract += filterToggle.Visible ? toggleButtonsSubtract : 0.0f;
|
listContainerSubtract += filterToggle.Visible ? toggleButtonsSubtract : 0.0f;
|
||||||
listContainerSubtract += serverPreviewToggleButton.Visible ? toggleButtonsSubtract : 0.0f;
|
listContainerSubtract += serverPreviewContainer.Visible ? toggleButtonsSubtract : 0.0f;
|
||||||
|
|
||||||
serverListContainer.RectTransform.RelativeSize = new Vector2(1.0f - listContainerSubtract, 1.0f);
|
serverListContainer.RectTransform.RelativeSize = new Vector2(1.0f - listContainerSubtract, 1.0f);
|
||||||
serverListHolder.Recalculate();
|
serverListHolder.Recalculate();
|
||||||
@@ -567,17 +568,17 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
joinButton.Enabled = true;
|
joinButton.Enabled = true;
|
||||||
selectedServer = serverInfo;
|
selectedServer = serverInfo;
|
||||||
if (!serverPreview.Visible)
|
if (!serverPreviewContainer.Visible)
|
||||||
{
|
{
|
||||||
serverPreview.RectTransform.RelativeSize = new Vector2(sidebarWidth, 1.0f);
|
serverPreviewContainer.RectTransform.RelativeSize = new Vector2(sidebarWidth, 1.0f);
|
||||||
serverPreviewToggleButton.Visible = true;
|
serverPreviewToggleButton.Visible = true;
|
||||||
serverPreviewToggleButton.IgnoreLayoutGroups = false;
|
serverPreviewToggleButton.IgnoreLayoutGroups = false;
|
||||||
serverPreview.Visible = true;
|
serverPreviewContainer.Visible = true;
|
||||||
serverPreview.IgnoreLayoutGroups = false;
|
serverPreviewContainer.IgnoreLayoutGroups = false;
|
||||||
RecalculateHolder();
|
RecalculateHolder();
|
||||||
}
|
}
|
||||||
serverInfo.CreatePreviewWindow(serverPreview);
|
serverInfo.CreatePreviewWindow(serverPreview.Content);
|
||||||
btn.Children.ForEach(c => c.SpriteEffects = serverPreview.Visible ? SpriteEffects.None : SpriteEffects.FlipHorizontally);
|
btn.Children.ForEach(c => c.SpriteEffects = serverPreviewContainer.Visible ? SpriteEffects.None : SpriteEffects.FlipHorizontally);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -592,24 +593,28 @@ namespace Barotrauma
|
|||||||
Visible = false,
|
Visible = false,
|
||||||
OnClicked = (btn, userdata) =>
|
OnClicked = (btn, userdata) =>
|
||||||
{
|
{
|
||||||
serverPreview.RectTransform.RelativeSize = new Vector2(0.2f, 1.0f);
|
serverPreviewContainer.RectTransform.RelativeSize = new Vector2(0.2f, 1.0f);
|
||||||
serverPreview.Visible = !serverPreview.Visible;
|
serverPreviewContainer.Visible = !serverPreviewContainer.Visible;
|
||||||
serverPreview.IgnoreLayoutGroups = !serverPreview.Visible;
|
serverPreviewContainer.IgnoreLayoutGroups = !serverPreviewContainer.Visible;
|
||||||
|
|
||||||
RecalculateHolder();
|
RecalculateHolder();
|
||||||
|
|
||||||
btn.Children.ForEach(c => c.SpriteEffects = serverPreview.Visible ? SpriteEffects.None : SpriteEffects.FlipHorizontally);
|
btn.Children.ForEach(c => c.SpriteEffects = serverPreviewContainer.Visible ? SpriteEffects.None : SpriteEffects.FlipHorizontally);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
serverPreview = new GUIFrame(new RectTransform(new Vector2(sidebarWidth, 1.0f), serverListHolder.RectTransform, Anchor.Center), style: null)
|
serverPreviewContainer = new GUIFrame(new RectTransform(new Vector2(sidebarWidth, 1.0f), serverListHolder.RectTransform, Anchor.Center), style: null)
|
||||||
{
|
{
|
||||||
Color = new Color(12, 14, 15, 255) * 0.5f,
|
Color = new Color(12, 14, 15, 255) * 0.5f,
|
||||||
OutlineColor = Color.Black,
|
OutlineColor = Color.Black,
|
||||||
IgnoreLayoutGroups = true,
|
IgnoreLayoutGroups = true,
|
||||||
Visible = false
|
Visible = false
|
||||||
};
|
};
|
||||||
|
serverPreview = new GUIListBox(new RectTransform(Vector2.One, serverPreviewContainer.RectTransform, Anchor.Center))
|
||||||
|
{
|
||||||
|
Padding = Vector4.One * 10 * GUI.Scale
|
||||||
|
};
|
||||||
|
|
||||||
// Spacing
|
// Spacing
|
||||||
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), bottomRow.RectTransform), style: null);
|
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), bottomRow.RectTransform), style: null);
|
||||||
@@ -1697,7 +1702,7 @@ namespace Barotrauma
|
|||||||
UpdateFriendsList();
|
UpdateFriendsList();
|
||||||
|
|
||||||
serverList.ClearChildren();
|
serverList.ClearChildren();
|
||||||
serverPreview.ClearChildren();
|
serverPreview.Content.ClearChildren();
|
||||||
joinButton.Enabled = false;
|
joinButton.Enabled = false;
|
||||||
selectedServer = null;
|
selectedServer = null;
|
||||||
|
|
||||||
|
|||||||
@@ -1604,7 +1604,7 @@ namespace Barotrauma
|
|||||||
if (string.IsNullOrEmpty(file) || !File.Exists(file)) { continue; }
|
if (string.IsNullOrEmpty(file) || !File.Exists(file)) { continue; }
|
||||||
|
|
||||||
string modFolder = Path.GetDirectoryName(itemContentPackage.Path);
|
string modFolder = Path.GetDirectoryName(itemContentPackage.Path);
|
||||||
string filePathRelativeToModFolder = UpdaterUtil.GetRelativePath(file, Path.Combine(Environment.CurrentDirectory, modFolder));
|
string filePathRelativeToModFolder = Path.GetRelativePath(Path.Combine(Environment.CurrentDirectory, modFolder), file);
|
||||||
|
|
||||||
//file is not inside the mod folder, we need to move it
|
//file is not inside the mod folder, we need to move it
|
||||||
if (filePathRelativeToModFolder.StartsWith("..") ||
|
if (filePathRelativeToModFolder.StartsWith("..") ||
|
||||||
|
|||||||
@@ -0,0 +1,125 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Barotrauma.Items.Components;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This screen only exists because I'm going mental without access to EnC on Linux.
|
||||||
|
* This is fucking stupid and horrible.
|
||||||
|
* Remember to remove this crap eventually.
|
||||||
|
* - Markus
|
||||||
|
*/
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
class TestScreen : EditorScreen
|
||||||
|
{
|
||||||
|
public override Camera Cam { get; }
|
||||||
|
|
||||||
|
private Item? miniMapItem;
|
||||||
|
|
||||||
|
private Submarine? submarine;
|
||||||
|
private Character? dummyCharacter;
|
||||||
|
public static Effect BlueprintEffect;
|
||||||
|
|
||||||
|
public TestScreen()
|
||||||
|
{
|
||||||
|
Cam = new Camera();
|
||||||
|
BlueprintEffect = GameMain.GameScreen.BlueprintEffect;
|
||||||
|
|
||||||
|
new GUIButton(new RectTransform(new Point(256, 256), Frame.RectTransform), "Reload shader")
|
||||||
|
{
|
||||||
|
OnClicked = (button, o) =>
|
||||||
|
{
|
||||||
|
BlueprintEffect.Dispose();
|
||||||
|
GameMain.Instance.Content.Unload();
|
||||||
|
BlueprintEffect = GameMain.Instance.Content.Load<Effect>("Effects/blueprintshader_opengl");
|
||||||
|
GameMain.GameScreen.BlueprintEffect = BlueprintEffect;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Select()
|
||||||
|
{
|
||||||
|
base.Select();
|
||||||
|
|
||||||
|
if (dummyCharacter is { Removed: false })
|
||||||
|
{
|
||||||
|
dummyCharacter?.Remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ????????
|
||||||
|
submarine = new Submarine(SubmarineInfo.SavedSubmarines.FirstOrDefault(info => info.Name.Equals("Kastrull", StringComparison.OrdinalIgnoreCase)));
|
||||||
|
miniMapItem = new Item(ItemPrefab.Find(null, "statusmonitor"), Vector2.Zero, submarine);
|
||||||
|
MiniMap miniMap = miniMapItem.GetComponent<MiniMap>();
|
||||||
|
miniMap.PowerConsumption = 0;
|
||||||
|
|
||||||
|
dummyCharacter = Character.Create(CharacterPrefab.HumanSpeciesName, Vector2.Zero, "", id: Entity.DummyID, hasAi: false);
|
||||||
|
dummyCharacter.Info.Name = "Galldren";
|
||||||
|
dummyCharacter.Inventory.CreateSlots();
|
||||||
|
|
||||||
|
Character.Controlled = dummyCharacter;
|
||||||
|
GameMain.World.ProcessChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void AddToGUIUpdateList()
|
||||||
|
{
|
||||||
|
Frame.AddToGUIUpdateList();
|
||||||
|
CharacterHUD.AddToGUIUpdateList(dummyCharacter);
|
||||||
|
dummyCharacter?.SelectedConstruction?.AddToGUIUpdateList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(double deltaTime)
|
||||||
|
{
|
||||||
|
base.Update(deltaTime);
|
||||||
|
|
||||||
|
if (dummyCharacter is { } dummy && miniMapItem is { } item)
|
||||||
|
{
|
||||||
|
if (dummy.SelectedConstruction != item)
|
||||||
|
{
|
||||||
|
dummy.SelectedConstruction = item;
|
||||||
|
}
|
||||||
|
dummy.SelectedConstruction?.UpdateHUD(Cam, dummy, (float)deltaTime);
|
||||||
|
Vector2 pos = FarseerPhysics.ConvertUnits.ToSimUnits(item.Position);
|
||||||
|
foreach (Limb limb in dummy.AnimController.Limbs)
|
||||||
|
{
|
||||||
|
limb.body.SetTransform(pos, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dummy.AnimController?.Collider is { } collider)
|
||||||
|
{
|
||||||
|
collider.SetTransform(pos, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
dummy.ControlLocalPlayer((float)deltaTime, Cam, false);
|
||||||
|
dummy.Control((float)deltaTime, Cam);
|
||||||
|
dummy.Submarine = submarine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
|
||||||
|
{
|
||||||
|
base.Draw(deltaTime, graphics, spriteBatch);
|
||||||
|
graphics.Clear(BackgroundColor);
|
||||||
|
|
||||||
|
spriteBatch.Begin(SpriteSortMode.BackToFront, transformMatrix: Cam.Transform);
|
||||||
|
miniMapItem?.Draw(spriteBatch, false);
|
||||||
|
if (dummyCharacter is { } dummy)
|
||||||
|
{
|
||||||
|
dummyCharacter.DrawFront(spriteBatch, Cam);
|
||||||
|
dummyCharacter.Draw(spriteBatch, Cam);
|
||||||
|
}
|
||||||
|
spriteBatch.End();
|
||||||
|
|
||||||
|
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState);
|
||||||
|
|
||||||
|
GUI.Draw(Cam, spriteBatch);
|
||||||
|
|
||||||
|
dummyCharacter?.DrawHUD(spriteBatch, Cam, false);
|
||||||
|
|
||||||
|
spriteBatch.End();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -38,6 +38,7 @@ namespace Barotrauma
|
|||||||
public readonly string File;
|
public readonly string File;
|
||||||
public readonly string Type;
|
public readonly string Type;
|
||||||
public readonly bool DuckVolume;
|
public readonly bool DuckVolume;
|
||||||
|
public readonly float Volume;
|
||||||
|
|
||||||
public readonly Vector2 IntensityRange;
|
public readonly Vector2 IntensityRange;
|
||||||
|
|
||||||
@@ -52,6 +53,7 @@ namespace Barotrauma
|
|||||||
this.Type = element.GetAttributeString("type", "").ToLowerInvariant();
|
this.Type = element.GetAttributeString("type", "").ToLowerInvariant();
|
||||||
this.IntensityRange = element.GetAttributeVector2("intensityrange", new Vector2(0.0f, 100.0f));
|
this.IntensityRange = element.GetAttributeVector2("intensityrange", new Vector2(0.0f, 100.0f));
|
||||||
this.DuckVolume = element.GetAttributeBool("duckvolume", false);
|
this.DuckVolume = element.GetAttributeBool("duckvolume", false);
|
||||||
|
this.Volume = element.GetAttributeFloat("volume", 1.0f);
|
||||||
this.ContinueFromPreviousTime = element.GetAttributeBool("continuefromprevioustime", false);
|
this.ContinueFromPreviousTime = element.GetAttributeBool("continuefromprevioustime", false);
|
||||||
this.Element = element;
|
this.Element = element;
|
||||||
}
|
}
|
||||||
@@ -816,6 +818,8 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int noiseLoopIndex = 1;
|
||||||
|
|
||||||
updateMusicTimer -= deltaTime;
|
updateMusicTimer -= deltaTime;
|
||||||
if (updateMusicTimer <= 0.0f)
|
if (updateMusicTimer <= 0.0f)
|
||||||
{
|
{
|
||||||
@@ -851,7 +855,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int noiseLoopIndex = 1;
|
|
||||||
if (Level.Loaded?.Type == LevelData.LevelType.LocationConnection)
|
if (Level.Loaded?.Type == LevelData.LevelType.LocationConnection)
|
||||||
{
|
{
|
||||||
// Find background noise loop for the current biome
|
// Find background noise loop for the current biome
|
||||||
@@ -917,7 +920,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
//mute the channel
|
//mute the channel
|
||||||
musicChannel[i].Gain = MathHelper.Lerp(musicChannel[i].Gain, 0.0f, MusicLerpSpeed * deltaTime);
|
musicChannel[i].Gain = MathHelper.Lerp(musicChannel[i].Gain, 0.0f, MusicLerpSpeed * deltaTime);
|
||||||
if (musicChannel[i].Gain < 0.01f) DisposeMusicChannel(i);
|
if (musicChannel[i].Gain < 0.01f) { DisposeMusicChannel(i); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//something should be playing, but the targetMusic is invalid
|
//something should be playing, but the targetMusic is invalid
|
||||||
@@ -932,7 +935,7 @@ namespace Barotrauma
|
|||||||
if (musicChannel[i] != null && musicChannel[i].IsPlaying)
|
if (musicChannel[i] != null && musicChannel[i].IsPlaying)
|
||||||
{
|
{
|
||||||
musicChannel[i].Gain = MathHelper.Lerp(musicChannel[i].Gain, 0.0f, MusicLerpSpeed * deltaTime);
|
musicChannel[i].Gain = MathHelper.Lerp(musicChannel[i].Gain, 0.0f, MusicLerpSpeed * deltaTime);
|
||||||
if (musicChannel[i].Gain < 0.01f) DisposeMusicChannel(i);
|
if (musicChannel[i].Gain < 0.01f) { DisposeMusicChannel(i); }
|
||||||
}
|
}
|
||||||
//channel free now, start playing the correct clip
|
//channel free now, start playing the correct clip
|
||||||
if (currentMusic[i] == null || (musicChannel[i] == null || !musicChannel[i].IsPlaying))
|
if (currentMusic[i] == null || (musicChannel[i] == null || !musicChannel[i].IsPlaying))
|
||||||
@@ -949,7 +952,7 @@ namespace Barotrauma
|
|||||||
targetMusic[i] = null;
|
targetMusic[i] = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
musicChannel[i] = currentMusic[i].Play(0.0f, "music");
|
musicChannel[i] = currentMusic[i].Play(0.0f, i == noiseLoopIndex ? "" : "music");
|
||||||
if (targetMusic[i].ContinueFromPreviousTime)
|
if (targetMusic[i].ContinueFromPreviousTime)
|
||||||
{
|
{
|
||||||
musicChannel[i].StreamSeekPos = targetMusic[i].PreviousTime;
|
musicChannel[i].StreamSeekPos = targetMusic[i].PreviousTime;
|
||||||
@@ -963,13 +966,13 @@ namespace Barotrauma
|
|||||||
if (musicChannel[i] == null || !musicChannel[i].IsPlaying)
|
if (musicChannel[i] == null || !musicChannel[i].IsPlaying)
|
||||||
{
|
{
|
||||||
musicChannel[i]?.Dispose();
|
musicChannel[i]?.Dispose();
|
||||||
musicChannel[i] = currentMusic[i].Play(0.0f, "music");
|
musicChannel[i] = currentMusic[i].Play(0.0f, i == noiseLoopIndex ? "" : "music");
|
||||||
musicChannel[i].Looping = true;
|
musicChannel[i].Looping = true;
|
||||||
}
|
}
|
||||||
float targetGain = 1.0f;
|
float targetGain = targetMusic[i].Volume;
|
||||||
if (targetMusic[i].DuckVolume)
|
if (targetMusic[i].DuckVolume)
|
||||||
{
|
{
|
||||||
targetGain = (float)Math.Sqrt(1.0f / activeTrackCount);
|
targetGain *= (float)Math.Sqrt(1.0f / activeTrackCount);
|
||||||
}
|
}
|
||||||
musicChannel[i].Gain = MathHelper.Lerp(musicChannel[i].Gain, targetGain, MusicLerpSpeed * deltaTime);
|
musicChannel[i].Gain = MathHelper.Lerp(musicChannel[i].Gain, targetGain, MusicLerpSpeed * deltaTime);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using Color = Microsoft.Xna.Framework.Color;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -55,6 +56,225 @@ namespace Barotrauma
|
|||||||
return isInside;
|
return isInside;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Vector2 GetPolygonBoundingBoxSize(List<Vector2> verticess)
|
||||||
|
{
|
||||||
|
float minX = verticess[0].X;
|
||||||
|
float maxX = verticess[0].X;
|
||||||
|
float minY = verticess[0].Y;
|
||||||
|
float maxY = verticess[0].Y;
|
||||||
|
|
||||||
|
foreach (var (vertX, vertY) in verticess)
|
||||||
|
{
|
||||||
|
minX = Math.Min(vertX, minX);
|
||||||
|
maxX = Math.Max(vertX, maxX);
|
||||||
|
minY = Math.Min(vertY, minY);
|
||||||
|
maxY = Math.Max(vertY, maxY);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Vector2(maxX - minX, maxY - minY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Vector2> ScalePolygon(List<Vector2> vertices, Vector2 scale)
|
||||||
|
{
|
||||||
|
List<Vector2> newVertices = new List<Vector2>();
|
||||||
|
|
||||||
|
Vector2 center = GetPolygonCentroid(vertices);
|
||||||
|
|
||||||
|
foreach (Vector2 vert in vertices)
|
||||||
|
{
|
||||||
|
Vector2 centerVector = vert - center;
|
||||||
|
Vector2 centerVectorScale = centerVector * scale;
|
||||||
|
Vector2 scaledVector = centerVectorScale + center;
|
||||||
|
newVertices.Add(scaledVector);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newVertices;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector2 GetPolygonCentroid(List<Vector2> poly)
|
||||||
|
{
|
||||||
|
float accumulatedArea = 0.0f;
|
||||||
|
float centerX = 0.0f;
|
||||||
|
float centerY = 0.0f;
|
||||||
|
|
||||||
|
for (int i = 0, j = poly.Count - 1; i < poly.Count; j = i++)
|
||||||
|
{
|
||||||
|
float temp = poly[i].X * poly[j].Y - poly[j].X * poly[i].Y;
|
||||||
|
accumulatedArea += temp;
|
||||||
|
centerX += (poly[i].X + poly[j].X) * temp;
|
||||||
|
centerY += (poly[i].Y + poly[j].Y) * temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Math.Abs(accumulatedArea) < 1E-7f) { return Vector2.Zero; } // Avoid division by zero
|
||||||
|
|
||||||
|
accumulatedArea *= 3f;
|
||||||
|
return new Vector2(centerX / accumulatedArea, centerY / accumulatedArea);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Vector2> SnapVertices(List<Vector2> points, int treshold = 1)
|
||||||
|
{
|
||||||
|
Stack<Vector2> toCheck = new Stack<Vector2>();
|
||||||
|
List<Vector2> newPoints = new List<Vector2>();
|
||||||
|
|
||||||
|
foreach (Vector2 point in points)
|
||||||
|
{
|
||||||
|
toCheck.Push(point);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (toCheck.TryPop(out Vector2 point))
|
||||||
|
{
|
||||||
|
Vector2 newPoint = new Vector2(point.X, point.Y);
|
||||||
|
foreach (Vector2 otherPoint in toCheck.Concat(newPoints))
|
||||||
|
{
|
||||||
|
float diffX = Math.Abs(newPoint.X - otherPoint.X),
|
||||||
|
diffY = Math.Abs(newPoint.Y - otherPoint.Y);
|
||||||
|
|
||||||
|
if (diffX <= treshold)
|
||||||
|
{
|
||||||
|
newPoint.X = Math.Max(newPoint.X, otherPoint.X);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (diffY <= treshold)
|
||||||
|
{
|
||||||
|
newPoint.Y = Math.Max(newPoint.Y, otherPoint.Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newPoints.Add(newPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newPoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ImmutableArray<RectangleF> SnapRectangles(IEnumerable<RectangleF> rects, int treshold = 1)
|
||||||
|
{
|
||||||
|
List<RectangleF> list = new List<RectangleF>();
|
||||||
|
|
||||||
|
List<Vector2> points = new List<Vector2>();
|
||||||
|
|
||||||
|
foreach (RectangleF rect in rects)
|
||||||
|
{
|
||||||
|
points.Add(new Vector2(rect.Left, rect.Top));
|
||||||
|
points.Add(new Vector2(rect.Right, rect.Top));
|
||||||
|
points.Add(new Vector2(rect.Right, rect.Bottom));
|
||||||
|
points.Add(new Vector2(rect.Left, rect.Bottom));
|
||||||
|
}
|
||||||
|
|
||||||
|
points = SnapVertices(points, treshold);
|
||||||
|
|
||||||
|
for (int i = 0; i < points.Count; i += 4)
|
||||||
|
{
|
||||||
|
Vector2 topLeft = points[i];
|
||||||
|
Vector2 bottomRight = points[i + 2];
|
||||||
|
|
||||||
|
list.Add(new RectangleF(topLeft, bottomRight - topLeft));
|
||||||
|
}
|
||||||
|
|
||||||
|
return list.ToImmutableArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<List<Vector2>> CombineRectanglesIntoShape(IEnumerable<RectangleF> rectangles)
|
||||||
|
{
|
||||||
|
List<Vector2> points =
|
||||||
|
(from point in rectangles.SelectMany(RectangleToPoints)
|
||||||
|
group point by point
|
||||||
|
into g
|
||||||
|
where g.Count() % 2 == 1
|
||||||
|
select g.Key)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
List<Vector2> sortedY = points.OrderBy(p => p.Y).ThenByDescending(p => p.X).ToList();
|
||||||
|
List<Vector2> sortedX = points.OrderBy(p => p.X).ThenByDescending(p => p.Y).ToList();
|
||||||
|
|
||||||
|
Dictionary<Vector2, Vector2> edgesH = new Dictionary<Vector2, Vector2>();
|
||||||
|
Dictionary<Vector2, Vector2> edgesV = new Dictionary<Vector2, Vector2>();
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
while (i < points.Count)
|
||||||
|
{
|
||||||
|
float currY = sortedY[i].Y;
|
||||||
|
|
||||||
|
while (i < points.Count && Math.Abs(sortedY[i].Y - currY) < 0.01f)
|
||||||
|
{
|
||||||
|
edgesH[sortedY[i]] = sortedY[i + 1];
|
||||||
|
edgesH[sortedY[i + 1]] = sortedY[i];
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
while (i < points.Count)
|
||||||
|
{
|
||||||
|
float currX = sortedX[i].X;
|
||||||
|
while (i < points.Count && Math.Abs(sortedX[i].X - currX) < 0.01f)
|
||||||
|
{
|
||||||
|
edgesV[sortedX[i]] = sortedX[i + 1];
|
||||||
|
edgesV[sortedX[i + 1]] = sortedX[i];
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<List<Vector2>> polygons = new List<List<Vector2>>();
|
||||||
|
|
||||||
|
while (edgesH.Any())
|
||||||
|
{
|
||||||
|
var (key, _) = edgesH.First();
|
||||||
|
List<(Vector2 Point, int Direction)> polygon = new List<(Vector2 Point, int Direction)> { (key, 0) };
|
||||||
|
edgesH.Remove(key);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
var (curr, direction) = polygon[^1];
|
||||||
|
|
||||||
|
if (direction == 0)
|
||||||
|
{
|
||||||
|
Vector2 nextVertex = edgesV[curr];
|
||||||
|
edgesV.Remove(curr);
|
||||||
|
polygon.Add((nextVertex, 1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Vector2 nextVertex = edgesH[curr];
|
||||||
|
edgesH.Remove(curr);
|
||||||
|
polygon.Add((nextVertex, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (polygon[^1] == polygon[0])
|
||||||
|
{
|
||||||
|
polygon.Remove(polygon[^1]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Vector2> poly = polygon.Select(t => t.Point).ToList();
|
||||||
|
|
||||||
|
foreach (Vector2 vertex in poly)
|
||||||
|
{
|
||||||
|
if (edgesH.ContainsKey(vertex))
|
||||||
|
{
|
||||||
|
edgesH.Remove(vertex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (edgesV.ContainsKey(vertex))
|
||||||
|
{
|
||||||
|
edgesV.Remove(vertex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
polygons.Add(poly);
|
||||||
|
}
|
||||||
|
|
||||||
|
return polygons;
|
||||||
|
|
||||||
|
static IEnumerable<Vector2> RectangleToPoints(RectangleF rect)
|
||||||
|
{
|
||||||
|
(float x1, float y1, float x2, float y2) = (rect.Left, rect.Top, rect.Right, rect.Bottom);
|
||||||
|
Vector2[] pts = { new Vector2(x1, y1), new Vector2(x2, y1), new Vector2(x2, y2), new Vector2(x1, y2) };
|
||||||
|
return pts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Convert an RGB value into an HLS value.
|
// Convert an RGB value into an HLS value.
|
||||||
public static Vector3 RgbToHLS(this Color color)
|
public static Vector3 RgbToHLS(this Color color)
|
||||||
{
|
{
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -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.14.9.0</Version>
|
<Version>0.1500.0.0</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.14.9.0</Version>
|
<Version>0.1500.0.0</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>
|
||||||
|
|||||||
@@ -67,3 +67,9 @@
|
|||||||
/processorParam:DebugMode=Auto
|
/processorParam:DebugMode=Auto
|
||||||
/build:grainshader.fx
|
/build:grainshader.fx
|
||||||
|
|
||||||
|
#begin blueprintshader.fx
|
||||||
|
/importer:EffectImporter
|
||||||
|
/processor:EffectProcessor
|
||||||
|
/processorParam:DebugMode=Auto
|
||||||
|
/build:blueprintshader.fx
|
||||||
|
|
||||||
|
|||||||
@@ -67,3 +67,8 @@
|
|||||||
/processorParam:DebugMode=Auto
|
/processorParam:DebugMode=Auto
|
||||||
/build:grainshader_opengl.fx
|
/build:grainshader_opengl.fx
|
||||||
|
|
||||||
|
#begin blueprintshader_opengl.fx
|
||||||
|
/importer:EffectImporter
|
||||||
|
/processor:EffectProcessor
|
||||||
|
/processorParam:DebugMode=Auto
|
||||||
|
/build:blueprintshader_opengl.fx
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
// vim:ft=hlsl
|
||||||
|
sampler TextureSampler : register(s0);
|
||||||
|
|
||||||
|
float width;
|
||||||
|
float height;
|
||||||
|
|
||||||
|
float3 sobel(float2 uv)
|
||||||
|
{
|
||||||
|
float x = 0;
|
||||||
|
float y = 0;
|
||||||
|
|
||||||
|
float w = 1.0 / width;
|
||||||
|
float h = 1.0 / height;
|
||||||
|
|
||||||
|
x += tex2D(TextureSampler, uv + float2(-w, -h)) * -1.0;
|
||||||
|
x += tex2D(TextureSampler, uv + float2(-w, 0)) * -2.0;
|
||||||
|
x += tex2D(TextureSampler, uv + float2(-w, h)) * -1.0;
|
||||||
|
|
||||||
|
x += tex2D(TextureSampler, uv + float2( w, -h)) * 1.0;
|
||||||
|
x += tex2D(TextureSampler, uv + float2( w, 0)) * 2.0;
|
||||||
|
x += tex2D(TextureSampler, uv + float2( w, h)) * 1.0;
|
||||||
|
|
||||||
|
y += tex2D(TextureSampler, uv + float2(-w, -h)) * -1.0;
|
||||||
|
y += tex2D(TextureSampler, uv + float2( 0, -h)) * -2.0;
|
||||||
|
y += tex2D(TextureSampler, uv + float2( w, -h)) * -1.0;
|
||||||
|
|
||||||
|
y += tex2D(TextureSampler, uv + float2(-w, h)) * 1.0;
|
||||||
|
y += tex2D(TextureSampler, uv + float2( 0, h)) * 2.0;
|
||||||
|
y += tex2D(TextureSampler, uv + float2( w, h)) * 1.0;
|
||||||
|
|
||||||
|
return sqrt(x * x + y * y);
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 blueprint(float4 position : SV_POSITION, float4 clr : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
|
||||||
|
{
|
||||||
|
float3 s = sobel(texCoord);
|
||||||
|
float a = tex2D(TextureSampler, texCoord).a;
|
||||||
|
a *= clr.a;
|
||||||
|
return float4(clr.r + s.r, clr.g + s.g, clr.b + s.b, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
technique Blueprint
|
||||||
|
{
|
||||||
|
pass Pass1
|
||||||
|
{
|
||||||
|
PixelShader = compile ps_4_0_level_9_1 blueprint();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
// vim:ft=hlsl
|
||||||
|
sampler TextureSampler : register(s0);
|
||||||
|
|
||||||
|
float width;
|
||||||
|
float height;
|
||||||
|
|
||||||
|
float3 sobel(float2 uv)
|
||||||
|
{
|
||||||
|
float x = 0;
|
||||||
|
float y = 0;
|
||||||
|
|
||||||
|
float w = 1.0 / width;
|
||||||
|
float h = 1.0 / height;
|
||||||
|
|
||||||
|
x += tex2D(TextureSampler, uv + float2(-w, -h)) * -1.0;
|
||||||
|
x += tex2D(TextureSampler, uv + float2(-w, 0)) * -2.0;
|
||||||
|
x += tex2D(TextureSampler, uv + float2(-w, h)) * -1.0;
|
||||||
|
|
||||||
|
x += tex2D(TextureSampler, uv + float2( w, -h)) * 1.0;
|
||||||
|
x += tex2D(TextureSampler, uv + float2( w, 0)) * 2.0;
|
||||||
|
x += tex2D(TextureSampler, uv + float2( w, h)) * 1.0;
|
||||||
|
|
||||||
|
y += tex2D(TextureSampler, uv + float2(-w, -h)) * -1.0;
|
||||||
|
y += tex2D(TextureSampler, uv + float2( 0, -h)) * -2.0;
|
||||||
|
y += tex2D(TextureSampler, uv + float2( w, -h)) * -1.0;
|
||||||
|
|
||||||
|
y += tex2D(TextureSampler, uv + float2(-w, h)) * 1.0;
|
||||||
|
y += tex2D(TextureSampler, uv + float2( 0, h)) * 2.0;
|
||||||
|
y += tex2D(TextureSampler, uv + float2( w, h)) * 1.0;
|
||||||
|
|
||||||
|
return sqrt(x * x + y * y);
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 blueprint(float4 position : SV_POSITION, float4 clr : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
|
||||||
|
{
|
||||||
|
float3 s = sobel(texCoord);
|
||||||
|
float a = tex2D(TextureSampler, texCoord).a;
|
||||||
|
a *= clr.a;
|
||||||
|
return float4(clr.r + s.r, clr.g + s.g, clr.b + s.b, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
technique Blueprint
|
||||||
|
{
|
||||||
|
pass Pass1
|
||||||
|
{
|
||||||
|
PixelShader = compile ps_3_0 blueprint();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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.14.9.0</Version>
|
<Version>0.1500.0.0</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.14.9.0</Version>
|
<Version>0.1500.0.0</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.14.9.0</Version>
|
<Version>0.1500.0.0</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>
|
||||||
|
|||||||
@@ -46,5 +46,10 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
partial void OnMoneyChanged(int prevAmount, int newAmount)
|
||||||
|
{
|
||||||
|
GameMain.NetworkMember.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.UpdateMoney });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -22,6 +23,14 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
partial void OnExperienceChanged(int prevAmount, int newAmount, Vector2 textPopupPos)
|
||||||
|
{
|
||||||
|
if (Math.Abs(prevAmount - newAmount) > 0)
|
||||||
|
{
|
||||||
|
GameMain.NetworkMember.CreateEntityEvent(Character, new object[] { NetEntityEvent.Type.UpdateExperience });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void ServerWrite(IWriteMessage msg)
|
public void ServerWrite(IWriteMessage msg)
|
||||||
{
|
{
|
||||||
msg.Write(ID);
|
msg.Write(ID);
|
||||||
@@ -53,6 +62,17 @@ namespace Barotrauma
|
|||||||
msg.Write((byte)0);
|
msg.Write((byte)0);
|
||||||
}
|
}
|
||||||
// TODO: animations
|
// TODO: animations
|
||||||
|
msg.Write((byte)savedStatValues.SelectMany(s => s.Value).Count());
|
||||||
|
foreach (var savedStatValuePair in savedStatValues)
|
||||||
|
{
|
||||||
|
foreach (var savedStatValue in savedStatValuePair.Value)
|
||||||
|
{
|
||||||
|
msg.Write((byte)savedStatValuePair.Key);
|
||||||
|
msg.Write(savedStatValue.StatIdentifier);
|
||||||
|
msg.Write(savedStatValue.StatValue);
|
||||||
|
msg.Write(savedStatValue.RemoveOnDeath);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -238,7 +238,7 @@ namespace Barotrauma
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ClientNetObject.ENTITY_STATE:
|
case ClientNetObject.ENTITY_STATE:
|
||||||
int eventType = msg.ReadRangedInteger(0, 3);
|
int eventType = msg.ReadRangedInteger(0, 4);
|
||||||
switch (eventType)
|
switch (eventType)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
@@ -268,8 +268,35 @@ namespace Barotrauma
|
|||||||
if (IsIncapacitated)
|
if (IsIncapacitated)
|
||||||
{
|
{
|
||||||
var causeOfDeath = CharacterHealth.GetCauseOfDeath();
|
var causeOfDeath = CharacterHealth.GetCauseOfDeath();
|
||||||
Kill(causeOfDeath.First, causeOfDeath.Second);
|
Kill(causeOfDeath.type, causeOfDeath.affliction);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case 3: // NetEntityEvent.Type.UpdateTalents
|
||||||
|
if (c.Character != this)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
DebugConsole.Log("Received a character update message from a client who's not controlling the character");
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the full list of talents from the player, only give the ones
|
||||||
|
// that are not already given (or otherwise not viable)
|
||||||
|
ushort talentCount = msg.ReadUInt16();
|
||||||
|
List<string> talentSelection = new List<string>();
|
||||||
|
for (int i = 0; i < talentCount; i++)
|
||||||
|
{
|
||||||
|
UInt32 talentIdentifier = msg.ReadUInt32();
|
||||||
|
var prefab = TalentPrefab.TalentPrefabs.Find(p => p.UIntIdentifier == talentIdentifier);
|
||||||
|
if (prefab != null) { talentSelection.Add(prefab.Identifier); }
|
||||||
|
}
|
||||||
|
talentSelection = TalentTree.CheckTalentSelection(this, talentSelection);
|
||||||
|
|
||||||
|
foreach (string talent in talentSelection)
|
||||||
|
{
|
||||||
|
GiveTalent(talent);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -283,7 +310,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (extraData != null)
|
if (extraData != null)
|
||||||
{
|
{
|
||||||
const int min = 0, max = 9;
|
const int min = 0, max = 12;
|
||||||
switch ((NetEntityEvent.Type)extraData[0])
|
switch ((NetEntityEvent.Type)extraData[0])
|
||||||
{
|
{
|
||||||
case NetEntityEvent.Type.InventoryState:
|
case NetEntityEvent.Type.InventoryState:
|
||||||
@@ -394,6 +421,22 @@ namespace Barotrauma
|
|||||||
msg.Write(inventoryItemIDs[i]);
|
msg.Write(inventoryItemIDs[i]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case NetEntityEvent.Type.UpdateExperience:
|
||||||
|
msg.WriteRangedInteger(10, min, max);
|
||||||
|
msg.Write(Info.ExperiencePoints);
|
||||||
|
break;
|
||||||
|
case NetEntityEvent.Type.UpdateTalents:
|
||||||
|
msg.WriteRangedInteger(11, min, max);
|
||||||
|
msg.Write((ushort)characterTalents.Count);
|
||||||
|
foreach (var unlockedTalent in characterTalents)
|
||||||
|
{
|
||||||
|
msg.Write(unlockedTalent.Prefab.UIntIdentifier);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NetEntityEvent.Type.UpdateMoney:
|
||||||
|
msg.WriteRangedInteger(12, min, max);
|
||||||
|
msg.Write(GameMain.GameSession.Campaign.Money);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
DebugConsole.ThrowError("Invalid NetworkEvent type for entity " + ToString() + " (" + (NetEntityEvent.Type)extraData[0] + ")");
|
DebugConsole.ThrowError("Invalid NetworkEvent type for entity " + ToString() + " (" + (NetEntityEvent.Type)extraData[0] + ")");
|
||||||
break;
|
break;
|
||||||
@@ -499,7 +542,7 @@ namespace Barotrauma
|
|||||||
if (writeStatus)
|
if (writeStatus)
|
||||||
{
|
{
|
||||||
WriteStatus(tempBuffer);
|
WriteStatus(tempBuffer);
|
||||||
(AIController as EnemyAIController)?.PetBehavior?.ServerWrite(tempBuffer);
|
AIController?.ServerWrite(tempBuffer);
|
||||||
HealthUpdatePending = false;
|
HealthUpdatePending = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1187,6 +1187,7 @@ namespace Barotrauma
|
|||||||
NewMessage("*****************", Color.Lime);
|
NewMessage("*****************", Color.Lime);
|
||||||
GameServer.Log("Console command \"restart\" executed: closing the server...", ServerLog.MessageType.ServerMessage);
|
GameServer.Log("Console command \"restart\" executed: closing the server...", ServerLog.MessageType.ServerMessage);
|
||||||
GameMain.Instance.CloseServer();
|
GameMain.Instance.CloseServer();
|
||||||
|
GameMain.Instance.TryStartChildServerRelay();
|
||||||
GameMain.Instance.StartServer();
|
GameMain.Instance.StartServer();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,17 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
public static readonly Version Version = Assembly.GetEntryAssembly().GetName().Version;
|
public static readonly Version Version = Assembly.GetEntryAssembly().GetName().Version;
|
||||||
|
|
||||||
public static World World;
|
|
||||||
|
private static World world;
|
||||||
|
public static World World
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (world == null) { world = new World(new Vector2(0, -9.82f)); }
|
||||||
|
return world;
|
||||||
|
}
|
||||||
|
set { world = value; }
|
||||||
|
}
|
||||||
public static GameSettings Config;
|
public static GameSettings Config;
|
||||||
|
|
||||||
public static GameServer Server;
|
public static GameServer Server;
|
||||||
@@ -123,6 +133,8 @@ namespace Barotrauma
|
|||||||
ItemAssemblyPrefab.LoadAll();
|
ItemAssemblyPrefab.LoadAll();
|
||||||
LevelObjectPrefab.LoadAll();
|
LevelObjectPrefab.LoadAll();
|
||||||
BallastFloraPrefab.LoadAll(GetFilesOfType(ContentType.MapCreature));
|
BallastFloraPrefab.LoadAll(GetFilesOfType(ContentType.MapCreature));
|
||||||
|
TalentPrefab.LoadAll(GetFilesOfType(ContentType.Talents));
|
||||||
|
TalentTree.LoadAll(GetFilesOfType(ContentType.TalentTrees));
|
||||||
|
|
||||||
GameModePreset.Init();
|
GameModePreset.Init();
|
||||||
DecalManager = new DecalManager();
|
DecalManager = new DecalManager();
|
||||||
@@ -179,6 +191,20 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool TryStartChildServerRelay()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < CommandLineArgs.Length; i++)
|
||||||
|
{
|
||||||
|
switch (CommandLineArgs[i].Trim())
|
||||||
|
{
|
||||||
|
case "-pipes":
|
||||||
|
ChildServerRelay.Start(CommandLineArgs[i + 2], CommandLineArgs[i + 1]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public void StartServer()
|
public void StartServer()
|
||||||
{
|
{
|
||||||
string name = "Server";
|
string name = "Server";
|
||||||
@@ -264,7 +290,7 @@ namespace Barotrauma
|
|||||||
i++;
|
i++;
|
||||||
break;
|
break;
|
||||||
case "-pipes":
|
case "-pipes":
|
||||||
ChildServerRelay.Start(CommandLineArgs[i + 2], CommandLineArgs[i + 1]);
|
//handled in TryStartChildServerRelay
|
||||||
i += 2;
|
i += 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -323,6 +349,7 @@ namespace Barotrauma
|
|||||||
Hyper.ComponentModel.HyperTypeDescriptionProvider.Add(typeof(Items.Components.ItemComponent));
|
Hyper.ComponentModel.HyperTypeDescriptionProvider.Add(typeof(Items.Components.ItemComponent));
|
||||||
Hyper.ComponentModel.HyperTypeDescriptionProvider.Add(typeof(Hull));
|
Hyper.ComponentModel.HyperTypeDescriptionProvider.Add(typeof(Hull));
|
||||||
|
|
||||||
|
TryStartChildServerRelay();
|
||||||
Init();
|
Init();
|
||||||
StartServer();
|
StartServer();
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,12 @@ namespace Barotrauma.Items.Components
|
|||||||
set { unsentChanges = value; }
|
set { unsentChanges = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void RemoveComponentSpecific()
|
||||||
|
{
|
||||||
|
base.RemoveComponentSpecific();
|
||||||
|
pathFinder = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void ServerRead(ClientNetObject type, IReadMessage msg, Barotrauma.Networking.Client c)
|
public void ServerRead(ClientNetObject type, IReadMessage msg, Barotrauma.Networking.Client c)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -289,6 +289,14 @@ namespace Barotrauma
|
|||||||
teamID = (byte)wifiComponent.TeamID;
|
teamID = (byte)wifiComponent.TeamID;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (teamID == 0)
|
||||||
|
{
|
||||||
|
foreach (IdCard idCard in GetComponents<IdCard>())
|
||||||
|
{
|
||||||
|
teamID = (byte)idCard.TeamID;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
msg.Write(teamID);
|
msg.Write(teamID);
|
||||||
bool tagsChanged = tags.Count != prefab.Tags.Count || !tags.All(t => prefab.Tags.Contains(t));
|
bool tagsChanged = tags.Count != prefab.Tags.Count || !tags.All(t => prefab.Tags.Contains(t));
|
||||||
|
|||||||
@@ -1,12 +1,4 @@
|
|||||||
using System;
|
using System.IO.Pipes;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using Barotrauma.IO;
|
|
||||||
using System.IO.Pipes;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.Win32.SafeHandles;
|
|
||||||
|
|
||||||
namespace Barotrauma.Networking
|
namespace Barotrauma.Networking
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2354,6 +2354,8 @@ namespace Barotrauma.Networking
|
|||||||
characterData.ApplyHealthData(spawnedCharacter);
|
characterData.ApplyHealthData(spawnedCharacter);
|
||||||
characterData.ApplyOrderData(spawnedCharacter);
|
characterData.ApplyOrderData(spawnedCharacter);
|
||||||
spawnedCharacter.GiveIdCardTags(mainSubWaypoints[i]);
|
spawnedCharacter.GiveIdCardTags(mainSubWaypoints[i]);
|
||||||
|
spawnedCharacter.LoadTalents();
|
||||||
|
|
||||||
characterData.HasSpawned = true;
|
characterData.HasSpawned = true;
|
||||||
}
|
}
|
||||||
spawnedCharacter.OwnerClientEndPoint = teamClients[i].Connection.EndPointString;
|
spawnedCharacter.OwnerClientEndPoint = teamClients[i].Connection.EndPointString;
|
||||||
@@ -2366,6 +2368,8 @@ namespace Barotrauma.Networking
|
|||||||
spawnedCharacter.TeamID = teamID;
|
spawnedCharacter.TeamID = teamID;
|
||||||
spawnedCharacter.GiveJobItems(mainSubWaypoints[i]);
|
spawnedCharacter.GiveJobItems(mainSubWaypoints[i]);
|
||||||
spawnedCharacter.GiveIdCardTags(mainSubWaypoints[i]);
|
spawnedCharacter.GiveIdCardTags(mainSubWaypoints[i]);
|
||||||
|
// talents are only avilable for players in online sessions, but modders or someone else might want to have them loaded anyway
|
||||||
|
spawnedCharacter.LoadTalents();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2431,6 +2435,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
roundStartTime = DateTime.Now;
|
roundStartTime = DateTime.Now;
|
||||||
|
|
||||||
|
startGameCoroutine = null;
|
||||||
yield return CoroutineStatus.Success;
|
yield return CoroutineStatus.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2619,8 +2624,8 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Submarine.Unload();
|
|
||||||
entityEventManager.Clear();
|
entityEventManager.Clear();
|
||||||
|
Submarine.Unload();
|
||||||
GameMain.NetLobbyScreen.Select();
|
GameMain.NetLobbyScreen.Select();
|
||||||
Log("Round ended.", ServerLog.MessageType.ServerMessage);
|
Log("Round ended.", ServerLog.MessageType.ServerMessage);
|
||||||
|
|
||||||
@@ -3145,28 +3150,19 @@ namespace Barotrauma.Networking
|
|||||||
public void SendOrderChatMessage(OrderChatMessage message)
|
public void SendOrderChatMessage(OrderChatMessage message)
|
||||||
{
|
{
|
||||||
if (message.Sender == null || message.Sender.SpeechImpediment >= 100.0f) { return; }
|
if (message.Sender == null || message.Sender.SpeechImpediment >= 100.0f) { return; }
|
||||||
//ChatMessageType messageType = ChatMessage.CanUseRadio(message.Sender) ? ChatMessageType.Radio : ChatMessageType.Default;
|
|
||||||
|
|
||||||
//check which clients can receive the message and apply distance effects
|
//check which clients can receive the message and apply distance effects
|
||||||
foreach (Client client in ConnectedClients)
|
foreach (Client client in ConnectedClients)
|
||||||
{
|
{
|
||||||
string modifiedMessage = message.Text;
|
if (message.Sender != null && client.Character != null && !client.Character.IsDead)
|
||||||
|
|
||||||
if (message.Sender != null &&
|
|
||||||
client.Character != null && !client.Character.IsDead)
|
|
||||||
{
|
{
|
||||||
//too far to hear the msg -> don't send
|
//too far to hear the msg -> don't send
|
||||||
if (!client.Character.CanHearCharacter(message.Sender)) { continue; }
|
if (!client.Character.CanHearCharacter(message.Sender)) { continue; }
|
||||||
}
|
}
|
||||||
|
|
||||||
SendDirectChatMessage(new OrderChatMessage(message.Order, message.OrderOption, message.OrderPriority, message.TargetEntity, message.TargetCharacter, message.Sender), client);
|
SendDirectChatMessage(new OrderChatMessage(message.Order, message.OrderOption, message.OrderPriority, message.TargetEntity, message.TargetCharacter, message.Sender), client);
|
||||||
}
|
}
|
||||||
|
if (!string.IsNullOrWhiteSpace(message.Text))
|
||||||
string myReceivedMessage = message.Text;
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(myReceivedMessage))
|
|
||||||
{
|
{
|
||||||
AddChatMessage(new OrderChatMessage(message.Order, message.OrderOption, message.OrderPriority, myReceivedMessage, message.TargetEntity, message.TargetCharacter, message.Sender));
|
AddChatMessage(new OrderChatMessage(message.Order, message.OrderOption, message.OrderPriority, message.Text, message.TargetEntity, message.TargetCharacter, message.Sender));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -44,11 +44,11 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
class ServerEntityEventManager : NetEntityEventManager
|
class ServerEntityEventManager : NetEntityEventManager
|
||||||
{
|
{
|
||||||
private List<ServerEntityEvent> events;
|
private readonly List<ServerEntityEvent> events;
|
||||||
|
|
||||||
//list of unique events (i.e. !IsDuplicate) created during the round
|
//list of unique events (i.e. !IsDuplicate) created during the round
|
||||||
//used for syncing clients who join mid-round
|
//used for syncing clients who join mid-round
|
||||||
private List<ServerEntityEvent> uniqueEvents;
|
private readonly List<ServerEntityEvent> uniqueEvents;
|
||||||
|
|
||||||
private UInt16 lastSentToAll;
|
private UInt16 lastSentToAll;
|
||||||
private UInt16 lastSentToAnyone;
|
private UInt16 lastSentToAnyone;
|
||||||
@@ -90,11 +90,11 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<BufferedEvent> bufferedEvents;
|
private readonly List<BufferedEvent> bufferedEvents;
|
||||||
|
|
||||||
private UInt16 ID;
|
private UInt16 ID;
|
||||||
|
|
||||||
private GameServer server;
|
private readonly GameServer server;
|
||||||
|
|
||||||
private double lastEventCountHighWarning;
|
private double lastEventCountHighWarning;
|
||||||
|
|
||||||
|
|||||||
@@ -284,6 +284,8 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
partial void RespawnCharactersProjSpecific(Vector2? shuttlePos)
|
partial void RespawnCharactersProjSpecific(Vector2? shuttlePos)
|
||||||
{
|
{
|
||||||
|
respawnedCharacters.Clear();
|
||||||
|
|
||||||
var respawnSub = RespawnShuttle ?? Submarine.MainSub;
|
var respawnSub = RespawnShuttle ?? Submarine.MainSub;
|
||||||
|
|
||||||
MultiPlayerCampaign campaign = GameMain.GameSession.GameMode as MultiPlayerCampaign;
|
MultiPlayerCampaign campaign = GameMain.GameSession.GameMode as MultiPlayerCampaign;
|
||||||
@@ -355,8 +357,21 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
characterInfos[i].ClearCurrentOrders();
|
characterInfos[i].ClearCurrentOrders();
|
||||||
|
|
||||||
var character = Character.Create(characterInfos[i], shuttleSpawnPoints[i].WorldPosition, characterInfos[i].Name, isRemotePlayer: !bot, hasAi: bot);
|
bool forceSpawnInMainSub = false;
|
||||||
|
if (!bot && campaign != null)
|
||||||
|
{
|
||||||
|
var matchingData = campaign?.GetClientCharacterData(clients[i]);
|
||||||
|
if (matchingData != null && !matchingData.HasSpawned)
|
||||||
|
{
|
||||||
|
forceSpawnInMainSub = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var character = Character.Create(characterInfos[i], (forceSpawnInMainSub ? mainSubSpawnPoints[i] : shuttleSpawnPoints[i]).WorldPosition, characterInfos[i].Name, isRemotePlayer: !bot, hasAi: bot);
|
||||||
character.TeamID = CharacterTeamType.Team1;
|
character.TeamID = CharacterTeamType.Team1;
|
||||||
|
character.LoadTalents();
|
||||||
|
|
||||||
|
respawnedCharacters.Add(character);
|
||||||
|
|
||||||
if (bot)
|
if (bot)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -185,7 +185,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
existingItems.Add(item);
|
existingItems.Add(item);
|
||||||
}
|
}
|
||||||
Entity.Spawner.AddToSpawnQueue(targetPrefab, targetContainer.OwnInventory);
|
Entity.Spawner.AddToSpawnQueue(targetPrefab, targetContainer.OwnInventory, null, item =>
|
||||||
|
{
|
||||||
|
item.AddTag("traitormissionitem");
|
||||||
|
});
|
||||||
target = null;
|
target = null;
|
||||||
}
|
}
|
||||||
else if (allowExisting)
|
else if (allowExisting)
|
||||||
|
|||||||
@@ -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.14.9.0</Version>
|
<Version>0.1500.0.0</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>
|
||||||
|
|||||||
@@ -63,6 +63,11 @@
|
|||||||
<Item file="Content/Items/Gardening/gardeningtools.xml" />
|
<Item file="Content/Items/Gardening/gardeningtools.xml" />
|
||||||
<Item file="Content/Items/Gardening/plantproducts.xml" />
|
<Item file="Content/Items/Gardening/plantproducts.xml" />
|
||||||
<Item file="Content/Map/Pirates/PirateItems.xml" />
|
<Item file="Content/Map/Pirates/PirateItems.xml" />
|
||||||
|
<Item file="Content/Items/Jobgear/Mechanic/mechanic_talent_items.xml" />
|
||||||
|
<Item file="Content/Items/Jobgear/Security/securityofficer_talent_items.xml" />
|
||||||
|
<Item file="Content/Items/Jobgear/Engineer/engineer_talent_items.xml" />
|
||||||
|
<Item file="Content/Items/Jobgear/Medic/medic_talent_items.xml" />
|
||||||
|
<Item file="Content/Items/Jobgear/Captain/captain_talent_items.xml" />
|
||||||
<Character file="Content/Characters/Balloon/Balloon.xml" />
|
<Character file="Content/Characters/Balloon/Balloon.xml" />
|
||||||
<Character file="Content/Characters/Carrier/Carrier.xml" />
|
<Character file="Content/Characters/Carrier/Carrier.xml" />
|
||||||
<Character file="Content/Characters/Charybdis/Charybdis.xml" />
|
<Character file="Content/Characters/Charybdis/Charybdis.xml" />
|
||||||
@@ -147,6 +152,12 @@
|
|||||||
<Text file="Content/Texts/Korean/KoreanVanilla.xml" />
|
<Text file="Content/Texts/Korean/KoreanVanilla.xml" />
|
||||||
<UIStyle file="Content/UI/style.xml" />
|
<UIStyle file="Content/UI/style.xml" />
|
||||||
<Afflictions file="Content/Afflictions.xml" />
|
<Afflictions file="Content/Afflictions.xml" />
|
||||||
|
<Afflictions file="Content/Talents/Assistant/AfflictionsAssistant.xml" />
|
||||||
|
<Afflictions file="Content/Talents/Captain/AfflictionsCaptain.xml" />
|
||||||
|
<Afflictions file="Content/Talents/Doctor/AfflictionsDoctor.xml" />
|
||||||
|
<Afflictions file="Content/Talents/Engineer/AfflictionsEngineer.xml" />
|
||||||
|
<Afflictions file="Content/Talents/Mechanic/AfflictionsMechanic.xml" />
|
||||||
|
<Afflictions file="Content/Talents/Security/AfflictionsSecurity.xml" />
|
||||||
<Structure file="Content/Map/StructurePrefabs.xml" />
|
<Structure file="Content/Map/StructurePrefabs.xml" />
|
||||||
<Structure file="Content/Map/Outposts/OutpostStructurePrefabs.xml" />
|
<Structure file="Content/Map/Outposts/OutpostStructurePrefabs.xml" />
|
||||||
<Structure file="Content/Map/Pirates/PirateStructures.xml" />
|
<Structure file="Content/Map/Pirates/PirateStructures.xml" />
|
||||||
@@ -261,4 +272,11 @@
|
|||||||
<EnemySubmarine file="Content/Map/EnemySubmarines/DugongPirate.sub"/>
|
<EnemySubmarine file="Content/Map/EnemySubmarines/DugongPirate.sub"/>
|
||||||
<EnemySubmarine file="Content/Map/EnemySubmarines/HumpbackPirate.sub"/>
|
<EnemySubmarine file="Content/Map/EnemySubmarines/HumpbackPirate.sub"/>
|
||||||
<EnemySubmarine file="Content/Map/EnemySubmarines/Typhon2Pirate.sub"/>
|
<EnemySubmarine file="Content/Map/EnemySubmarines/Typhon2Pirate.sub"/>
|
||||||
|
<Talents file="Content/Talents/Assistant/TalentsAssistant.xml"/>
|
||||||
|
<Talents file="Content/Talents/Security/TalentsSecurity.xml"/>
|
||||||
|
<Talents file="Content/Talents/Engineer/TalentsEngineer.xml"/>
|
||||||
|
<Talents file="Content/Talents/Mechanic/TalentsMechanic.xml"/>
|
||||||
|
<Talents file="Content/Talents/Captain/TalentsCaptain.xml"/>
|
||||||
|
<Talents file="Content/Talents/Doctor/TalentsDoctor.xml"/>
|
||||||
|
<TalentTrees file="Content/Talents/TalentTrees.xml"/>
|
||||||
</contentpackage>
|
</contentpackage>
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using Barotrauma.Items.Components;
|
||||||
|
using Barotrauma.Networking;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Barotrauma.Items.Components;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
@@ -328,5 +329,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
protected virtual void OnStateChanged(AIState from, AIState to) { }
|
protected virtual void OnStateChanged(AIState from, AIState to) { }
|
||||||
protected virtual void OnTargetChanged(AITarget previousTarget, AITarget newTarget) { }
|
protected virtual void OnTargetChanged(AITarget previousTarget, AITarget newTarget) { }
|
||||||
|
|
||||||
|
public virtual void ClientRead(IReadMessage msg) { }
|
||||||
|
public virtual void ServerWrite(IWriteMessage msg) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Barotrauma.Extensions;
|
using Barotrauma.Extensions;
|
||||||
using Barotrauma.Items.Components;
|
using Barotrauma.Items.Components;
|
||||||
|
using Barotrauma.Networking;
|
||||||
using FarseerPhysics;
|
using FarseerPhysics;
|
||||||
using FarseerPhysics.Dynamics;
|
using FarseerPhysics.Dynamics;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
@@ -37,6 +38,12 @@ namespace Barotrauma
|
|||||||
PreviousState = _state;
|
PreviousState = _state;
|
||||||
OnStateChanged(_state, value);
|
OnStateChanged(_state, value);
|
||||||
_state = value;
|
_state = value;
|
||||||
|
if (_state == AIState.Attack)
|
||||||
|
{
|
||||||
|
#if CLIENT
|
||||||
|
Character.PlaySound(CharacterSound.SoundType.Attack, maxInterval: 3);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,6 +57,8 @@ namespace Barotrauma
|
|||||||
private readonly float updateTargetsInterval = 1;
|
private readonly float updateTargetsInterval = 1;
|
||||||
private readonly float updateMemoriesInverval = 1;
|
private readonly float updateMemoriesInverval = 1;
|
||||||
private readonly float attackLimbResetInterval = 2;
|
private readonly float attackLimbResetInterval = 2;
|
||||||
|
// Min priority for the memorized targets. The actual value fades gradually, unless kept fresh by selecting the target.
|
||||||
|
private const float minPriority = 10;
|
||||||
|
|
||||||
private readonly float avoidLookAheadDistance;
|
private readonly float avoidLookAheadDistance;
|
||||||
|
|
||||||
@@ -394,7 +403,7 @@ namespace Barotrauma
|
|||||||
public void SelectTarget(AITarget target, float priority)
|
public void SelectTarget(AITarget target, float priority)
|
||||||
{
|
{
|
||||||
SelectedAiTarget = target;
|
SelectedAiTarget = target;
|
||||||
selectedTargetMemory = GetTargetMemory(target, true);
|
selectedTargetMemory = GetTargetMemory(target, addIfNotFound: true);
|
||||||
selectedTargetMemory.Priority = priority;
|
selectedTargetMemory.Priority = priority;
|
||||||
ignoredTargets.Remove(target);
|
ignoredTargets.Remove(target);
|
||||||
}
|
}
|
||||||
@@ -641,7 +650,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Character c = a.Character;
|
Character c = a.Character;
|
||||||
if (c.IsDead || c.Removed) { return false; }
|
if (c.IsDead || c.Removed) { return false; }
|
||||||
if (!IsFriendly(Character, c)) { return true; }
|
if (!Character.IsFriendly(c)) { return true; }
|
||||||
// Only apply the threshold to friendly characters
|
// Only apply the threshold to friendly characters
|
||||||
return a.Damage >= selectedTargetingParams.DamageThreshold;
|
return a.Damage >= selectedTargetingParams.DamageThreshold;
|
||||||
}
|
}
|
||||||
@@ -976,7 +985,7 @@ namespace Barotrauma
|
|||||||
Character owner = GetOwner(item);
|
Character owner = GetOwner(item);
|
||||||
if (owner != null)
|
if (owner != null)
|
||||||
{
|
{
|
||||||
if (IsFriendly(Character, owner))
|
if (Character.IsFriendly(owner))
|
||||||
{
|
{
|
||||||
ResetAITarget();
|
ResetAITarget();
|
||||||
State = AIState.Idle;
|
State = AIState.Idle;
|
||||||
@@ -1337,7 +1346,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
canAttack = Character.CharacterList.All(c => c == Character || !IsFriendly(Character, c) || IsFarEnough(c));
|
canAttack = Character.CharacterList.All(c => c == Character || !Character.IsFriendly(c) || IsFarEnough(c));
|
||||||
}
|
}
|
||||||
if (canAttack)
|
if (canAttack)
|
||||||
{
|
{
|
||||||
@@ -1356,7 +1365,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
hitTarget = limb.character;
|
hitTarget = limb.character;
|
||||||
}
|
}
|
||||||
if (hitTarget != null && !hitTarget.IsDead && IsFriendly(Character, hitTarget))
|
if (hitTarget != null && !hitTarget.IsDead && Character.IsFriendly(hitTarget))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1764,7 +1773,7 @@ namespace Barotrauma
|
|||||||
Character.AnimController.ReleaseStuckLimbs();
|
Character.AnimController.ReleaseStuckLimbs();
|
||||||
LatchOntoAI?.DeattachFromBody(reset: true, cooldown: 1);
|
LatchOntoAI?.DeattachFromBody(reset: true, cooldown: 1);
|
||||||
if (attacker == null || attacker.AiTarget == null || attacker.Removed || attacker.IsDead) { return; }
|
if (attacker == null || attacker.AiTarget == null || attacker.Removed || attacker.IsDead) { return; }
|
||||||
bool isFriendly = IsFriendly(Character, attacker);
|
bool isFriendly = Character.IsFriendly(attacker);
|
||||||
if (wasLatched)
|
if (wasLatched)
|
||||||
{
|
{
|
||||||
State = AIState.Escape;
|
State = AIState.Escape;
|
||||||
@@ -1840,7 +1849,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AITargetMemory targetMemory = GetTargetMemory(attacker.AiTarget, true);
|
AITargetMemory targetMemory = GetTargetMemory(attacker.AiTarget, addIfNotFound: true);
|
||||||
targetMemory.Priority += GetRelativeDamage(attackResult.Damage, Character.Vitality) * AIParams.AggressionHurt;
|
targetMemory.Priority += GetRelativeDamage(attackResult.Damage, Character.Vitality) * AIParams.AggressionHurt;
|
||||||
|
|
||||||
// Only allow to react once. Otherwise would attack the target with only a fraction of a cooldown
|
// Only allow to react once. Otherwise would attack the target with only a fraction of a cooldown
|
||||||
@@ -1884,16 +1893,15 @@ namespace Barotrauma
|
|||||||
private bool UpdateLimbAttack(float deltaTime, Limb attackingLimb, Vector2 attackSimPos, float distance = -1, Limb targetLimb = null)
|
private bool UpdateLimbAttack(float deltaTime, Limb attackingLimb, Vector2 attackSimPos, float distance = -1, Limb targetLimb = null)
|
||||||
{
|
{
|
||||||
if (SelectedAiTarget?.Entity == null) { return false; }
|
if (SelectedAiTarget?.Entity == null) { return false; }
|
||||||
|
if (attackingLimb?.attack == null) { return false; }
|
||||||
ActiveAttack = attackingLimb?.attack;
|
ActiveAttack = attackingLimb.attack;
|
||||||
|
|
||||||
if (wallTarget != null)
|
if (wallTarget != null)
|
||||||
{
|
{
|
||||||
// If the selected target is not the wall target, make the wall target the selected target.
|
// If the selected target is not the wall target, make the wall target the selected target.
|
||||||
var aiTarget = wallTarget.Structure.AiTarget;
|
var aiTarget = wallTarget.Structure.AiTarget;
|
||||||
if (aiTarget != null && SelectedAiTarget != aiTarget)
|
if (aiTarget != null && SelectedAiTarget != aiTarget)
|
||||||
{
|
{
|
||||||
SelectTarget(aiTarget, GetTargetMemory(SelectedAiTarget, true).Priority);
|
SelectTarget(aiTarget, GetTargetMemory(SelectedAiTarget, addIfNotFound: true).Priority);
|
||||||
State = AIState.Attack;
|
State = AIState.Attack;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1902,23 +1910,35 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
//simulate attack input to get the character to attack client-side
|
//simulate attack input to get the character to attack client-side
|
||||||
Character.SetInput(InputType.Attack, true, true);
|
Character.SetInput(InputType.Attack, true, true);
|
||||||
#if SERVER
|
if (!ActiveAttack.IsRunning)
|
||||||
GameMain.NetworkMember.CreateEntityEvent(Character, new object[]
|
|
||||||
{
|
{
|
||||||
|
#if SERVER
|
||||||
|
GameMain.NetworkMember.CreateEntityEvent(Character, new object[]
|
||||||
|
{
|
||||||
Networking.NetEntityEvent.Type.SetAttackTarget,
|
Networking.NetEntityEvent.Type.SetAttackTarget,
|
||||||
attackingLimb,
|
attackingLimb,
|
||||||
(damageTarget as Entity)?.ID ?? Entity.NullEntityID,
|
(damageTarget as Entity)?.ID ?? Entity.NullEntityID,
|
||||||
damageTarget is Character character && targetLimb != null ? Array.IndexOf(character.AnimController.Limbs, targetLimb) : 0,
|
damageTarget is Character character && targetLimb != null ? Array.IndexOf(character.AnimController.Limbs, targetLimb) : 0,
|
||||||
SimPosition.X,
|
SimPosition.X,
|
||||||
SimPosition.Y
|
SimPosition.Y
|
||||||
});
|
});
|
||||||
|
#else
|
||||||
|
Character.PlaySound(CharacterSound.SoundType.Attack, maxInterval: 3);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
if (attackingLimb.UpdateAttack(deltaTime, attackSimPos, damageTarget, out AttackResult attackResult, distance, targetLimb))
|
if (attackingLimb.UpdateAttack(deltaTime, attackSimPos, damageTarget, out AttackResult attackResult, distance, targetLimb))
|
||||||
{
|
{
|
||||||
if (damageTarget.Health > 0 && attackResult.Damage > 0)
|
if (damageTarget.Health > 0 && attackResult.Damage > 0)
|
||||||
{
|
{
|
||||||
// Managed to hit a living/non-destroyed target. Increase the priority more if the target is low in health -> dies easily/soon
|
// Managed to hit a living/non-destroyed target. Increase the priority more if the target is low in health -> dies easily/soon
|
||||||
selectedTargetMemory.Priority += GetRelativeDamage(attackResult.Damage, damageTarget.Health) * AIParams.AggressionGreed;
|
float greed = AIParams.AggressionGreed;
|
||||||
|
if (!(damageTarget is Character))
|
||||||
|
{
|
||||||
|
// Halve the greed for attacking non-characters.
|
||||||
|
greed /= 2;
|
||||||
|
}
|
||||||
|
selectedTargetMemory.Priority += GetRelativeDamage(attackResult.Damage, damageTarget.Health) * greed;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2125,6 +2145,9 @@ namespace Barotrauma
|
|||||||
string targetingTag = null;
|
string targetingTag = null;
|
||||||
if (targetCharacter != null)
|
if (targetCharacter != null)
|
||||||
{
|
{
|
||||||
|
// ignore if target is tagged to be explicitly ignored (Feign Death)
|
||||||
|
if (targetCharacter.HasAbilityFlag(AbilityFlags.IgnoredByEnemyAI)) { continue; }
|
||||||
|
|
||||||
if (targetCharacter.IsDead)
|
if (targetCharacter.IsDead)
|
||||||
{
|
{
|
||||||
targetingTag = "dead";
|
targetingTag = "dead";
|
||||||
@@ -2139,7 +2162,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (IsFriendly(Character, targetCharacter))
|
if (Character.IsFriendly(targetCharacter))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -2449,7 +2472,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (otherCharacter == character) { continue; }
|
if (otherCharacter == character) { continue; }
|
||||||
if (otherCharacter.AIController?.SelectedAiTarget != aiTarget) { continue; }
|
if (otherCharacter.AIController?.SelectedAiTarget != aiTarget) { continue; }
|
||||||
if (!IsFriendly(character, otherCharacter)) { continue; }
|
if (!character.IsFriendly(otherCharacter)) { continue; }
|
||||||
valueModifier /= 2;
|
valueModifier /= 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2469,7 +2492,7 @@ namespace Barotrauma
|
|||||||
// -> just ignore the distance and attack whatever has the highest priority
|
// -> just ignore the distance and attack whatever has the highest priority
|
||||||
dist = Math.Max(dist, 100.0f);
|
dist = Math.Max(dist, 100.0f);
|
||||||
|
|
||||||
AITargetMemory targetMemory = GetTargetMemory(aiTarget, true);
|
AITargetMemory targetMemory = GetTargetMemory(aiTarget, addIfNotFound: true);
|
||||||
if (Character.CurrentHull != null && Math.Abs(toTarget.Y) > Character.CurrentHull.Size.Y)
|
if (Character.CurrentHull != null && Math.Abs(toTarget.Y) > Character.CurrentHull.Size.Y)
|
||||||
{
|
{
|
||||||
// Inside the sub, treat objects that are up or down, as they were farther away.
|
// Inside the sub, treat objects that are up or down, as they were farther away.
|
||||||
@@ -2527,7 +2550,7 @@ namespace Barotrauma
|
|||||||
// Don't target items that we own.
|
// Don't target items that we own.
|
||||||
// This is a rare case, and almost entirely related to Humanhusks, so let's check it last to reduce unnecessary checks (although the check shouldn't be expensive)
|
// This is a rare case, and almost entirely related to Humanhusks, so let's check it last to reduce unnecessary checks (although the check shouldn't be expensive)
|
||||||
if (owner == character) { continue; }
|
if (owner == character) { continue; }
|
||||||
if (owner != null && (IsFriendly(Character, owner) || owner.AiTarget != null && ignoredTargets.Contains(owner.AiTarget)))
|
if (owner != null && (Character.IsFriendly(owner) || owner.AiTarget != null && ignoredTargets.Contains(owner.AiTarget)))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -2599,7 +2622,7 @@ namespace Barotrauma
|
|||||||
wall = wallTarget?.Structure;
|
wall = wallTarget?.Structure;
|
||||||
}
|
}
|
||||||
// The target is not a wall or it's not the same as we are attached to -> release
|
// The target is not a wall or it's not the same as we are attached to -> release
|
||||||
bool releaseTarget = wall == null || (!wall.Bodies.Contains(LatchOntoAI.AttachJoints[0].BodyB) && wall.Submarine?.PhysicsBody?.FarseerBody != LatchOntoAI.AttachJoints[0].BodyB);
|
bool releaseTarget = wall?.Bodies == null || (!wall.Bodies.Contains(LatchOntoAI.AttachJoints[0].BodyB) && wall.Submarine?.PhysicsBody?.FarseerBody != LatchOntoAI.AttachJoints[0].BodyB);
|
||||||
if (!releaseTarget)
|
if (!releaseTarget)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < wall.Sections.Length; i++)
|
for (int i = 0; i < wall.Sections.Length; i++)
|
||||||
@@ -2847,10 +2870,15 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (addIfNotFound)
|
if (addIfNotFound)
|
||||||
{
|
{
|
||||||
memory = new AITargetMemory(target, 10);
|
memory = new AITargetMemory(target, minPriority);
|
||||||
targetMemories.Add(target, memory);
|
targetMemories.Add(target, memory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (addIfNotFound)
|
||||||
|
{
|
||||||
|
// Keep the memory alive.
|
||||||
|
memory.Priority = Math.Max(memory.Priority, minPriority);
|
||||||
|
}
|
||||||
return memory;
|
return memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3014,7 +3042,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (!onlyExisting && !tempParams.ContainsKey(tag))
|
if (!onlyExisting && !tempParams.ContainsKey(tag))
|
||||||
{
|
{
|
||||||
if (AIParams.TryAddNewTarget(tag, state, priority ?? 100, out targetParams))
|
if (AIParams.TryAddNewTarget(tag, state, priority ?? minPriority, out targetParams))
|
||||||
{
|
{
|
||||||
tempParams.Add(tag, targetParams);
|
tempParams.Add(tag, targetParams);
|
||||||
}
|
}
|
||||||
@@ -3051,6 +3079,7 @@ namespace Barotrauma
|
|||||||
ChangeParams(target.SpeciesName, state, priority);
|
ChangeParams(target.SpeciesName, state, priority);
|
||||||
if (target.IsHuman)
|
if (target.IsHuman)
|
||||||
{
|
{
|
||||||
|
priority = GetTargetParams("human")?.Priority;
|
||||||
// Target also items, because if we are blind and the target doesn't move, we can only perceive the target when it uses items
|
// Target also items, because if we are blind and the target doesn't move, we can only perceive the target when it uses items
|
||||||
if (state == AIState.Attack || state == AIState.Escape)
|
if (state == AIState.Attack || state == AIState.Escape)
|
||||||
{
|
{
|
||||||
@@ -3061,20 +3090,19 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
// If the target is shooting from the submarine, we might not perceive it because it doesn't move.
|
// If the target is shooting from the submarine, we might not perceive it because it doesn't move.
|
||||||
// --> Target the submarine too.
|
// --> Target the submarine too.
|
||||||
if (target.Submarine != null && (canAttackDoors || canAttackWalls))
|
if (target.Submarine != null && Character.Submarine == null && (canAttackDoors || canAttackWalls))
|
||||||
{
|
{
|
||||||
ChangeParams("room", state, priority);
|
ChangeParams("room", state, priority * 0.1f);
|
||||||
if (canAttackWalls)
|
if (canAttackWalls)
|
||||||
{
|
{
|
||||||
ChangeParams("wall", state, priority);
|
ChangeParams("wall", state, priority * 0.1f);
|
||||||
}
|
}
|
||||||
if (canAttackDoors)
|
if (canAttackDoors)
|
||||||
{
|
{
|
||||||
ChangeParams("door", state, priority);
|
ChangeParams("door", state, priority * 0.1f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ChangeParams("provocative", state, priority, onlyExisting: true);
|
ChangeParams("provocative", state, priority, onlyExisting: true);
|
||||||
ChangeParams("light", state, priority, onlyExisting: true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3306,7 +3334,17 @@ namespace Barotrauma
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsFriendly(Character me, Character other) => other.SpeciesName == me.SpeciesName || other.Params.CompareGroup(me.Params.Group);
|
public override void ServerWrite(IWriteMessage msg)
|
||||||
|
{
|
||||||
|
msg.Write((byte)State);
|
||||||
|
PetBehavior?.ServerWrite(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ClientRead(IReadMessage msg)
|
||||||
|
{
|
||||||
|
State = (AIState)msg.ReadByte();
|
||||||
|
PetBehavior?.ClientRead(msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//the "memory" of the Character
|
//the "memory" of the Character
|
||||||
|
|||||||
@@ -915,10 +915,10 @@ namespace Barotrauma
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ReportProblem(Character reporter, Order order)
|
public static void ReportProblem(Character reporter, Order order, Hull targetHull = null)
|
||||||
{
|
{
|
||||||
if (reporter == null || order == null) { return; }
|
if (reporter == null || order == null) { return; }
|
||||||
var visibleHulls = new List<Hull>(reporter.GetVisibleHulls());
|
var visibleHulls = targetHull is null ? new List<Hull>(reporter.GetVisibleHulls()) : new List<Hull> { targetHull };
|
||||||
foreach (var hull in visibleHulls)
|
foreach (var hull in visibleHulls)
|
||||||
{
|
{
|
||||||
PropagateHullSafety(reporter, hull);
|
PropagateHullSafety(reporter, hull);
|
||||||
@@ -1415,7 +1415,7 @@ namespace Barotrauma
|
|||||||
if (GameMain.GameSession?.Campaign?.Map?.CurrentLocation != null)
|
if (GameMain.GameSession?.Campaign?.Map?.CurrentLocation != null)
|
||||||
{
|
{
|
||||||
var reputationLoss = damageAmount * Reputation.ReputationLossPerWallDamage;
|
var reputationLoss = damageAmount * Reputation.ReputationLossPerWallDamage;
|
||||||
GameMain.GameSession.Campaign.Map.CurrentLocation.Reputation.Value -= reputationLoss;
|
GameMain.GameSession.Campaign.Map.CurrentLocation.Reputation.AddReputation(-reputationLoss);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (accumulatedDamage <= WarningThreshold) { return; }
|
if (accumulatedDamage <= WarningThreshold) { return; }
|
||||||
@@ -1510,7 +1510,7 @@ namespace Barotrauma
|
|||||||
var reputationLoss = MathHelper.Clamp(
|
var reputationLoss = MathHelper.Clamp(
|
||||||
(item.Prefab.GetMinPrice() ?? 0) * Reputation.ReputationLossPerStolenItemPrice,
|
(item.Prefab.GetMinPrice() ?? 0) * Reputation.ReputationLossPerStolenItemPrice,
|
||||||
Reputation.MinReputationLossPerStolenItem, Reputation.MaxReputationLossPerStolenItem);
|
Reputation.MinReputationLossPerStolenItem, Reputation.MaxReputationLossPerStolenItem);
|
||||||
GameMain.GameSession.Campaign.Map.CurrentLocation.Reputation.Value -= reputationLoss;
|
GameMain.GameSession.Campaign.Map.CurrentLocation.Reputation.AddReputation(-reputationLoss);
|
||||||
}
|
}
|
||||||
item.StolenDuringRound = true;
|
item.StolenDuringRound = true;
|
||||||
otherCharacter.Speak(TextManager.Get("dialogstealwarning"), null, Rand.Range(0.5f, 1.0f), "thief", 10.0f);
|
otherCharacter.Speak(TextManager.Get("dialogstealwarning"), null, Rand.Range(0.5f, 1.0f), "thief", 10.0f);
|
||||||
@@ -1971,13 +1971,13 @@ namespace Barotrauma
|
|||||||
if (c.Removed) { continue; }
|
if (c.Removed) { continue; }
|
||||||
if (c.TeamID != Character.TeamID) { continue; }
|
if (c.TeamID != Character.TeamID) { continue; }
|
||||||
if (c.IsIncapacitated) { continue; }
|
if (c.IsIncapacitated) { continue; }
|
||||||
other = c;
|
|
||||||
if (c.IsPlayer)
|
if (c.IsPlayer)
|
||||||
{
|
{
|
||||||
if (c.SelectedConstruction == target.Item)
|
if (c.SelectedConstruction == target.Item)
|
||||||
{
|
{
|
||||||
// If the other character is player, don't try to operate
|
// If the other character is player, don't try to operate
|
||||||
return true;
|
other = c;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (c.AIController is HumanAIController operatingAI)
|
else if (c.AIController is HumanAIController operatingAI)
|
||||||
@@ -1991,7 +1991,8 @@ namespace Barotrauma
|
|||||||
if (!isOrder && isTargetOrdered)
|
if (!isOrder && isTargetOrdered)
|
||||||
{
|
{
|
||||||
// If the other bot is ordered to operate the item, let him do it, unless we are ordered too
|
// If the other bot is ordered to operate the item, let him do it, unless we are ordered too
|
||||||
return true;
|
other = c;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2012,18 +2013,20 @@ namespace Barotrauma
|
|||||||
// Steering is hard-coded -> cannot use the required skills collection defined in the xml
|
// Steering is hard-coded -> cannot use the required skills collection defined in the xml
|
||||||
if (Character.GetSkillLevel("helm") <= c.GetSkillLevel("helm"))
|
if (Character.GetSkillLevel("helm") <= c.GetSkillLevel("helm"))
|
||||||
{
|
{
|
||||||
return true;
|
other = c;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (target.DegreeOfSuccess(Character) <= target.DegreeOfSuccess(c))
|
else if (target.DegreeOfSuccess(Character) <= target.DegreeOfSuccess(c))
|
||||||
{
|
{
|
||||||
return true;
|
other = c;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return other != null;
|
||||||
bool IsOrderedToOperateThis(AIController ai) => ai is HumanAIController humanAI && humanAI.ObjectiveManager.CurrentOrder is AIObjectiveOperateItem operateOrder && operateOrder.Component.Item == target.Item;
|
bool IsOrderedToOperateThis(AIController ai) => ai is HumanAIController humanAI && humanAI.ObjectiveManager.CurrentOrder is AIObjectiveOperateItem operateOrder && operateOrder.Component.Item == target.Item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -161,12 +161,13 @@ namespace Barotrauma
|
|||||||
private Vector2 CalculateSteeringSeek(Vector2 target, float weight, Func<PathNode, bool> startNodeFilter = null, Func<PathNode, bool> endNodeFilter = null, Func<PathNode, bool> nodeFilter = null, bool checkVisibility = true)
|
private Vector2 CalculateSteeringSeek(Vector2 target, float weight, Func<PathNode, bool> startNodeFilter = null, Func<PathNode, bool> endNodeFilter = null, Func<PathNode, bool> nodeFilter = null, bool checkVisibility = true)
|
||||||
{
|
{
|
||||||
Vector2 targetDiff = target - currentTarget;
|
Vector2 targetDiff = target - currentTarget;
|
||||||
if (currentPath != null && currentPath.Nodes.Any())
|
if (currentPath != null && currentPath.Nodes.Any() && character.Submarine != null)
|
||||||
{
|
{
|
||||||
//current path calculated relative to a different sub than where the character is now
|
//target in a different sub than where the character is now
|
||||||
//take that into account when calculating if the target has moved
|
//take that into account when calculating if the target has moved
|
||||||
Submarine currentPathSub = currentPath?.Nodes.First().Submarine;
|
Submarine currentPathSub = currentPath?.CurrentNode?.Submarine;
|
||||||
if (currentPathSub != character.Submarine && character.Submarine != null)
|
if (currentPathSub == character.Submarine) { currentPathSub = currentPath?.Nodes.LastOrDefault()?.Submarine; }
|
||||||
|
if (currentPathSub != character.Submarine && targetDiff.LengthSquared() > 1 && currentPathSub != null)
|
||||||
{
|
{
|
||||||
Vector2 subDiff = character.Submarine.SimPosition - currentPathSub.SimPosition;
|
Vector2 subDiff = character.Submarine.SimPosition - currentPathSub.SimPosition;
|
||||||
targetDiff += subDiff;
|
targetDiff += subDiff;
|
||||||
|
|||||||
+9
-8
@@ -101,11 +101,11 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public enum CombatMode
|
public enum CombatMode
|
||||||
{
|
{
|
||||||
Defensive,
|
Defensive, // Use weapons against the enemy, but try to retreat to a safe place
|
||||||
Offensive,
|
Offensive, // Engage the enemy and keep attacking it
|
||||||
Arrest,
|
Arrest, // Try to arrest the enemy without using lethal weapons (stunning + handcuffs)
|
||||||
Retreat,
|
Retreat, // Run to a safe place without attacking the target
|
||||||
None
|
None // Don't use
|
||||||
}
|
}
|
||||||
|
|
||||||
public CombatMode Mode { get; private set; }
|
public CombatMode Mode { get; private set; }
|
||||||
@@ -958,14 +958,15 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
if (reloadTimer > 0) { return; }
|
if (reloadTimer > 0) { return; }
|
||||||
if (holdFireCondition != null && holdFireCondition()) { return; }
|
if (holdFireCondition != null && holdFireCondition()) { return; }
|
||||||
float sqrDist = Vector2.DistanceSquared(character.Position, Enemy.Position);
|
sqrDistance = Vector2.DistanceSquared(character.WorldPosition, Enemy.WorldPosition);
|
||||||
|
distanceTimer = distanceCheckInterval;
|
||||||
if (WeaponComponent is MeleeWeapon meleeWeapon)
|
if (WeaponComponent is MeleeWeapon meleeWeapon)
|
||||||
{
|
{
|
||||||
bool closeEnough = true;
|
bool closeEnough = true;
|
||||||
float sqrRange = meleeWeapon.Range * meleeWeapon.Range;
|
float sqrRange = meleeWeapon.Range * meleeWeapon.Range;
|
||||||
if (character.AnimController.InWater)
|
if (character.AnimController.InWater)
|
||||||
{
|
{
|
||||||
if (sqrDist > sqrRange)
|
if (sqrDistance > sqrRange)
|
||||||
{
|
{
|
||||||
closeEnough = false;
|
closeEnough = false;
|
||||||
}
|
}
|
||||||
@@ -1003,7 +1004,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (WeaponComponent is RepairTool repairTool)
|
if (WeaponComponent is RepairTool repairTool)
|
||||||
{
|
{
|
||||||
if (sqrDist > repairTool.Range * repairTool.Range) { return; }
|
if (sqrDistance > repairTool.Range * repairTool.Range) { return; }
|
||||||
}
|
}
|
||||||
float aimFactor = MathHelper.PiOver2 * (1 - AimAccuracy);
|
float aimFactor = MathHelper.PiOver2 * (1 - AimAccuracy);
|
||||||
if (VectorExtensions.Angle(VectorExtensions.Forward(Weapon.body.TransformedRotation), Enemy.Position - Weapon.Position) < MathHelper.PiOver4 + aimFactor)
|
if (VectorExtensions.Angle(VectorExtensions.Forward(Weapon.body.TransformedRotation), Enemy.Position - Weapon.Position) < MathHelper.PiOver4 + aimFactor)
|
||||||
|
|||||||
+6
-2
@@ -53,9 +53,13 @@ namespace Barotrauma
|
|||||||
distanceFactor = 1;
|
distanceFactor = 1;
|
||||||
}
|
}
|
||||||
float severity = AIObjectiveExtinguishFires.GetFireSeverity(targetHull);
|
float severity = AIObjectiveExtinguishFires.GetFireSeverity(targetHull);
|
||||||
if (severity > 0.5f && !isOrder)
|
if (severity > 0.75f && !isOrder &&
|
||||||
|
targetHull.RoomName != null &&
|
||||||
|
!targetHull.RoomName.Contains("reactor", StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
!targetHull.RoomName.Contains("engine", StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
!targetHull.RoomName.Contains("command", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
// Ignore severe fires unless ordered. (Let the fire drain all the oxygen instead).
|
// Ignore severe fires to prevent casualities unless ordered to extinguish.
|
||||||
Priority = 0;
|
Priority = 0;
|
||||||
Abandon = true;
|
Abandon = true;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ namespace Barotrauma
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 0-1 based on the horizontal size of all of the fires in the hull.
|
/// 0-1 based on the horizontal size of all of the fires in the hull.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static float GetFireSeverity(Hull hull) => MathHelper.Lerp(0, 1, MathUtils.InverseLerp(0, Math.Min(hull.Rect.Width, 1000), hull.FireSources.Sum(fs => fs.Size.X)));
|
public static float GetFireSeverity(Hull hull) => MathHelper.Lerp(0, 1, MathUtils.InverseLerp(0, 500, hull.FireSources.Sum(fs => fs.Size.X)));
|
||||||
|
|
||||||
protected override IEnumerable<Hull> GetList() => Hull.hullList;
|
protected override IEnumerable<Hull> GetList() => Hull.hullList;
|
||||||
|
|
||||||
|
|||||||
+1
@@ -63,6 +63,7 @@ namespace Barotrauma
|
|||||||
if (target.CurrentHull == null) { return false; }
|
if (target.CurrentHull == null) { return false; }
|
||||||
if (HumanAIController.IsFriendly(character, target)) { return false; }
|
if (HumanAIController.IsFriendly(character, target)) { return false; }
|
||||||
if (!character.Submarine.IsConnectedTo(target.Submarine)) { return false; }
|
if (!character.Submarine.IsConnectedTo(target.Submarine)) { return false; }
|
||||||
|
if (target.HasAbilityFlag(AbilityFlags.IgnoredByEnemyAI)) { return false; }
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-15
@@ -57,7 +57,20 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
onAbandon: () => Abandon = true,
|
onAbandon: () => Abandon = true,
|
||||||
onCompleted: () => RemoveSubObjective(ref getDivingGear));
|
onCompleted: () =>
|
||||||
|
{
|
||||||
|
RemoveSubObjective(ref getDivingGear);
|
||||||
|
if (gearTag == HEAVY_DIVING_GEAR && HumanAIController.HasItem(character, LIGHT_DIVING_GEAR, out IEnumerable<Item> masks, requireEquipped: true))
|
||||||
|
{
|
||||||
|
foreach (Item mask in masks)
|
||||||
|
{
|
||||||
|
if (mask != targetItem)
|
||||||
|
{
|
||||||
|
character.Inventory.TryPutItem(mask, character, CharacterInventory.anySlot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -71,9 +84,13 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (character.IsOnPlayerTeam)
|
if (character.IsOnPlayerTeam)
|
||||||
{
|
{
|
||||||
if (HumanAIController.HasItem(character, "oxygensource", out _, conditionPercentage: min))
|
if (HumanAIController.HasItem(character, OXYGEN_SOURCE, out _, conditionPercentage: min))
|
||||||
{
|
{
|
||||||
character.Speak(TextManager.Get("dialogswappingoxygentank"), null, 0, "swappingoxygentank", 30.0f);
|
character.Speak(TextManager.Get("dialogswappingoxygentank"), null, 0, "swappingoxygentank", 30.0f);
|
||||||
|
if (character.Inventory.FindAllItems(i => i.HasTag(OXYGEN_SOURCE) && i.Condition > min).Count == 1)
|
||||||
|
{
|
||||||
|
character.Speak(TextManager.Get("dialoglastoxygentank"), null, 0.0f, "dialoglastoxygentank", 30.0f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -105,7 +122,7 @@ namespace Barotrauma
|
|||||||
onAbandon: () =>
|
onAbandon: () =>
|
||||||
{
|
{
|
||||||
Abandon = true;
|
Abandon = true;
|
||||||
if (remainingTanks > 0 && !HumanAIController.HasItem(character, "oxygensource", out _, conditionPercentage: 0.01f))
|
if (remainingTanks > 0 && !HumanAIController.HasItem(character, OXYGEN_SOURCE, out _, conditionPercentage: 0.01f))
|
||||||
{
|
{
|
||||||
character.Speak(TextManager.Get("dialogcantfindtoxygen"), null, 0, "cantfindoxygen", 30.0f);
|
character.Speak(TextManager.Get("dialogcantfindtoxygen"), null, 0, "cantfindoxygen", 30.0f);
|
||||||
}
|
}
|
||||||
@@ -121,7 +138,7 @@ namespace Barotrauma
|
|||||||
int ReportOxygenTankCount()
|
int ReportOxygenTankCount()
|
||||||
{
|
{
|
||||||
if (character.Submarine != Submarine.MainSub) { return 1; }
|
if (character.Submarine != Submarine.MainSub) { return 1; }
|
||||||
int remainingOxygenTanks = Submarine.MainSub.GetItems(false).Count(i => i.HasTag("oxygensource") && i.Condition > 1);
|
int remainingOxygenTanks = Submarine.MainSub.GetItems(false).Count(i => i.HasTag(OXYGEN_SOURCE) && i.Condition > 1);
|
||||||
if (remainingOxygenTanks == 0)
|
if (remainingOxygenTanks == 0)
|
||||||
{
|
{
|
||||||
character.Speak(TextManager.Get("DialogOutOfOxygenTanks"), null, 0.0f, "outofoxygentanks", 30.0f);
|
character.Speak(TextManager.Get("DialogOutOfOxygenTanks"), null, 0.0f, "outofoxygentanks", 30.0f);
|
||||||
@@ -136,17 +153,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns false only when no inventory can be found from the item.
|
|
||||||
/// </summary>
|
|
||||||
public static bool EjectEmptyTanks(Character actor, Item target, out IEnumerable<Item> containedItems)
|
|
||||||
{
|
|
||||||
containedItems = target.OwnInventory?.AllItems;
|
|
||||||
if (containedItems == null) { return false; }
|
|
||||||
AIController.UnequipEmptyItems(actor, target);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Reset()
|
public override void Reset()
|
||||||
{
|
{
|
||||||
base.Reset();
|
base.Reset();
|
||||||
|
|||||||
+7
-20
@@ -242,9 +242,8 @@ namespace Barotrauma
|
|||||||
if (!searchingNewHull)
|
if (!searchingNewHull)
|
||||||
{
|
{
|
||||||
//find all available hulls first
|
//find all available hulls first
|
||||||
FindTargetHulls();
|
|
||||||
searchingNewHull = true;
|
searchingNewHull = true;
|
||||||
return;
|
FindTargetHulls();
|
||||||
}
|
}
|
||||||
else if (targetHulls.Any())
|
else if (targetHulls.Any())
|
||||||
{
|
{
|
||||||
@@ -255,11 +254,10 @@ namespace Barotrauma
|
|||||||
var path = PathSteering.PathFinder.FindPath(character.SimPosition, currentTarget.SimPosition, errorMsgStr: null, nodeFilter: node =>
|
var path = PathSteering.PathFinder.FindPath(character.SimPosition, currentTarget.SimPosition, errorMsgStr: null, nodeFilter: node =>
|
||||||
{
|
{
|
||||||
if (node.Waypoint.CurrentHull == null) { return false; }
|
if (node.Waypoint.CurrentHull == null) { return false; }
|
||||||
// Check that there is no unsafe or forbidden hulls on the way to the target
|
// Check that there is no unsafe hulls on the way to the target
|
||||||
if (node.Waypoint.CurrentHull != character.CurrentHull && HumanAIController.UnsafeHulls.Contains(node.Waypoint.CurrentHull)) { return false; }
|
if (node.Waypoint.CurrentHull != character.CurrentHull && HumanAIController.UnsafeHulls.Contains(node.Waypoint.CurrentHull)) { return false; }
|
||||||
if (isCurrentHullAllowed && IsForbidden(node.Waypoint.CurrentHull)) { return false; }
|
|
||||||
return true;
|
return true;
|
||||||
});
|
}, endNodeFilter: node => !isCurrentHullAllowed | !IsForbidden(node.Waypoint.CurrentHull));
|
||||||
if (path.Unreachable)
|
if (path.Unreachable)
|
||||||
{
|
{
|
||||||
//can't go to this room, remove it from the list and try another room
|
//can't go to this room, remove it from the list and try another room
|
||||||
@@ -271,30 +269,19 @@ namespace Barotrauma
|
|||||||
SetTargetTimerLow();
|
SetTargetTimerLow();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
character.AIController.SelectTarget(currentTarget.AiTarget);
|
||||||
|
PathSteering.SetPath(path);
|
||||||
|
SetTargetTimerNormal();
|
||||||
searchingNewHull = false;
|
searchingNewHull = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Couldn't find a target for some reason -> reset
|
// Couldn't find a valid hull
|
||||||
SetTargetTimerHigh();
|
SetTargetTimerHigh();
|
||||||
searchingNewHull = false;
|
searchingNewHull = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentTarget != null)
|
|
||||||
{
|
|
||||||
character.AIController.SelectTarget(currentTarget.AiTarget);
|
|
||||||
string errorMsg = null;
|
|
||||||
#if DEBUG
|
|
||||||
bool isRoomNameFound = currentTarget.DisplayName != null;
|
|
||||||
errorMsg = "(Character " + character.Name + " idling, target " + (isRoomNameFound ? currentTarget.DisplayName : currentTarget.ToString()) + ")";
|
|
||||||
#endif
|
|
||||||
var path = PathSteering.PathFinder.FindPath(character.SimPosition, currentTarget.SimPosition, errorMsgStr: errorMsg, nodeFilter: node => node.Waypoint.CurrentHull != null);
|
|
||||||
PathSteering.SetPath(path);
|
|
||||||
}
|
|
||||||
SetTargetTimerNormal();
|
|
||||||
}
|
}
|
||||||
newTargetTimer -= deltaTime;
|
newTargetTimer -= deltaTime;
|
||||||
|
|
||||||
if (!character.IsClimbing && IsSteeringFinished())
|
if (!character.IsClimbing && IsSteeringFinished())
|
||||||
{
|
{
|
||||||
Wander(deltaTime);
|
Wander(deltaTime);
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ namespace Barotrauma
|
|||||||
public Entity TargetEntity;
|
public Entity TargetEntity;
|
||||||
public ItemComponent TargetItemComponent;
|
public ItemComponent TargetItemComponent;
|
||||||
public readonly bool UseController;
|
public readonly bool UseController;
|
||||||
|
public readonly string[] ControllerTags;
|
||||||
public Controller ConnectedController;
|
public Controller ConnectedController;
|
||||||
|
|
||||||
public Character OrderGiver;
|
public Character OrderGiver;
|
||||||
@@ -309,6 +310,7 @@ namespace Barotrauma
|
|||||||
color = orderElement.GetAttributeColor("color");
|
color = orderElement.GetAttributeColor("color");
|
||||||
FadeOutTime = orderElement.GetAttributeFloat("fadeouttime", 0.0f);
|
FadeOutTime = orderElement.GetAttributeFloat("fadeouttime", 0.0f);
|
||||||
UseController = orderElement.GetAttributeBool("usecontroller", false);
|
UseController = orderElement.GetAttributeBool("usecontroller", false);
|
||||||
|
ControllerTags = orderElement.GetAttributeStringArray("controllertags", new string[0]);
|
||||||
TargetAllCharacters = orderElement.GetAttributeBool("targetallcharacters", false);
|
TargetAllCharacters = orderElement.GetAttributeBool("targetallcharacters", false);
|
||||||
AppropriateJobs = orderElement.GetAttributeStringArray("appropriatejobs", new string[0]);
|
AppropriateJobs = orderElement.GetAttributeStringArray("appropriatejobs", new string[0]);
|
||||||
Options = orderElement.GetAttributeStringArray("options", new string[0]);
|
Options = orderElement.GetAttributeStringArray("options", new string[0]);
|
||||||
@@ -380,6 +382,7 @@ namespace Barotrauma
|
|||||||
SymbolSprite = prefab.SymbolSprite;
|
SymbolSprite = prefab.SymbolSprite;
|
||||||
Color = prefab.Color;
|
Color = prefab.Color;
|
||||||
UseController = prefab.UseController;
|
UseController = prefab.UseController;
|
||||||
|
ControllerTags = prefab.ControllerTags;
|
||||||
TargetAllCharacters = prefab.TargetAllCharacters;
|
TargetAllCharacters = prefab.TargetAllCharacters;
|
||||||
AppropriateJobs = prefab.AppropriateJobs;
|
AppropriateJobs = prefab.AppropriateJobs;
|
||||||
FadeOutTime = prefab.FadeOutTime;
|
FadeOutTime = prefab.FadeOutTime;
|
||||||
@@ -399,7 +402,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (UseController)
|
if (UseController)
|
||||||
{
|
{
|
||||||
ConnectedController = targetItem.Item?.FindController();
|
ConnectedController = targetItem.Item?.FindController(tags: ControllerTags);
|
||||||
if (ConnectedController == null)
|
if (ConnectedController == null)
|
||||||
{
|
{
|
||||||
DebugConsole.AddWarning("AI: Tried to use a controller for operating an item, but couldn't find any.");
|
DebugConsole.AddWarning("AI: Tried to use a controller for operating an item, but couldn't find any.");
|
||||||
@@ -450,19 +453,37 @@ namespace Barotrauma
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetChatMessage(string targetCharacterName, string targetRoomName, bool givingOrderToSelf, string orderOption = "")
|
public string GetChatMessage(string targetCharacterName, string targetRoomName, bool givingOrderToSelf, string orderOption = "", int? priority = null)
|
||||||
{
|
{
|
||||||
orderOption ??= "";
|
priority ??= CharacterInfo.HighestManualOrderPriority;
|
||||||
|
// If the order has a lesser priority, it means we are rearranging character orders
|
||||||
string messageTag = (givingOrderToSelf && !TargetAllCharacters ? "OrderDialogSelf." : "OrderDialog.") + Identifier;
|
if (!TargetAllCharacters && priority != CharacterInfo.HighestManualOrderPriority && Identifier != "dismissed")
|
||||||
if (Identifier != "dismissed" && !string.IsNullOrEmpty(orderOption)) { messageTag += "." + orderOption; }
|
{
|
||||||
|
return TextManager.GetWithVariable("rearrangedorders", "[name]", targetCharacterName ?? string.Empty, returnNull: true) ?? string.Empty;
|
||||||
if (targetCharacterName == null) { targetCharacterName = ""; }
|
}
|
||||||
if (targetRoomName == null) { targetRoomName = ""; }
|
string messageTag = $"{(givingOrderToSelf && !TargetAllCharacters ? "OrderDialogSelf" : "OrderDialog")}";
|
||||||
string msg = TextManager.GetWithVariables(messageTag, new string[2] { "[name]", "[roomname]" }, new string[2] { targetCharacterName, targetRoomName }, new bool[2] { false, true }, true);
|
messageTag += $".{Identifier}";
|
||||||
if (msg == null) { return ""; }
|
if (!string.IsNullOrEmpty(orderOption))
|
||||||
|
{
|
||||||
return msg;
|
if (Identifier != "dismissed")
|
||||||
|
{
|
||||||
|
messageTag += $".{orderOption}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string[] splitOption = orderOption.Split('.');
|
||||||
|
if (splitOption.Length > 0)
|
||||||
|
{
|
||||||
|
messageTag += $".{splitOption[0]}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
string msg = TextManager.GetWithVariables(messageTag,
|
||||||
|
new string[2] { "[name]", "[roomname]" },
|
||||||
|
new string[2] { targetCharacterName ?? string.Empty, targetRoomName ?? string.Empty },
|
||||||
|
formatCapitals: new bool[2] { false, true },
|
||||||
|
returnNull: true);
|
||||||
|
return msg ?? string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -505,7 +526,7 @@ namespace Barotrauma
|
|||||||
if (item.NonInteractable) { continue; }
|
if (item.NonInteractable) { continue; }
|
||||||
if (ItemComponentType != null && item.Components.None(c => c.GetType() == ItemComponentType)) { continue; }
|
if (ItemComponentType != null && item.Components.None(c => c.GetType() == ItemComponentType)) { continue; }
|
||||||
Controller controller = null;
|
Controller controller = null;
|
||||||
if (UseController && !item.TryFindController(out controller)) { continue; }
|
if (UseController && !item.TryFindController(out controller, tags: ControllerTags)) { continue; }
|
||||||
if (interactableFor != null && (!item.IsInteractable(interactableFor) || (UseController && !controller.Item.IsInteractable(interactableFor)))) { continue; }
|
if (interactableFor != null && (!item.IsInteractable(interactableFor) || (UseController && !controller.Item.IsInteractable(interactableFor)))) { continue; }
|
||||||
matchingItems.Add(item);
|
matchingItems.Add(item);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,64 +97,51 @@ namespace Barotrauma
|
|||||||
|
|
||||||
foreach (WayPoint wp in wayPoints)
|
foreach (WayPoint wp in wayPoints)
|
||||||
{
|
{
|
||||||
wp.linkedTo.CollectionChanged += WaypointLinksChanged;
|
wp.OnLinksChanged += WaypointLinksChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
IndoorsSteering = indoorsSteering;
|
IndoorsSteering = indoorsSteering;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaypointLinksChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
void WaypointLinksChanged(WayPoint wp)
|
||||||
{
|
{
|
||||||
if (Submarine.Unloading) { return; }
|
if (Submarine.Unloading) { return; }
|
||||||
|
|
||||||
var waypoints = sender as IEnumerable<MapEntity>;
|
var node = nodes.Find(n => n.Waypoint == wp);
|
||||||
|
if (node == null) { return; }
|
||||||
|
|
||||||
foreach (MapEntity me in waypoints)
|
for (int i = node.connections.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
WayPoint wp = me as WayPoint;
|
//remove connection if the waypoint isn't connected anymore
|
||||||
if (me == null) { continue; }
|
if (wp.linkedTo.FirstOrDefault(l => l == node.connections[i].Waypoint) == null)
|
||||||
|
|
||||||
var node = nodes.Find(n => n.Waypoint == wp);
|
|
||||||
if (node == null) { return; }
|
|
||||||
|
|
||||||
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
|
|
||||||
{
|
{
|
||||||
for (int i = node.connections.Count - 1; i >= 0; i--)
|
node.connections.RemoveAt(i);
|
||||||
{
|
node.distances.RemoveAt(i);
|
||||||
//remove connection if the waypoint isn't connected anymore
|
|
||||||
if (wp.linkedTo.FirstOrDefault(l => l == node.connections[i].Waypoint) == null)
|
|
||||||
{
|
|
||||||
node.connections.RemoveAt(i);
|
|
||||||
node.distances.RemoveAt(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < wp.linkedTo.Count; i++)
|
||||||
|
{
|
||||||
|
if (!(wp.linkedTo[i] is WayPoint connected)) { continue; }
|
||||||
|
|
||||||
|
//already connected, continue
|
||||||
|
if (node.connections.Any(n => n.Waypoint == connected)) { continue; }
|
||||||
|
|
||||||
|
var matchingNode = nodes.Find(n => n.Waypoint == connected);
|
||||||
|
if (matchingNode == null)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < wp.linkedTo.Count; i++)
|
|
||||||
{
|
|
||||||
if (!(wp.linkedTo[i] is WayPoint connected)) { continue; }
|
|
||||||
|
|
||||||
//already connected, continue
|
|
||||||
if (node.connections.Any(n => n.Waypoint == connected)) { continue; }
|
|
||||||
|
|
||||||
var matchingNode = nodes.Find(n => n.Waypoint == connected);
|
|
||||||
if (matchingNode == null)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
DebugConsole.ThrowError("Waypoint connections were changed, no matching path node found in PathFinder");
|
DebugConsole.ThrowError("Waypoint connections were changed, no matching path node found in PathFinder");
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
node.connections.Add(matchingNode);
|
|
||||||
node.distances.Add(Vector2.Distance(node.Position, matchingNode.Position));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node.connections.Add(matchingNode);
|
||||||
|
node.distances.Add(Vector2.Distance(node.Position, matchingNode.Position));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly List<PathNode> sortedNodes = new List<PathNode>();
|
private readonly List<PathNode> sortedNodes = new List<PathNode>();
|
||||||
|
|
||||||
public SteeringPath FindPath(Vector2 start, Vector2 end, Submarine hostSub = null, string errorMsgStr = null, Func<PathNode, bool> startNodeFilter = null, Func<PathNode, bool> endNodeFilter = null, Func<PathNode, bool> nodeFilter = null, bool checkVisibility = true)
|
public SteeringPath FindPath(Vector2 start, Vector2 end, Submarine hostSub = null, string errorMsgStr = null, Func<PathNode, bool> startNodeFilter = null, Func<PathNode, bool> endNodeFilter = null, Func<PathNode, bool> nodeFilter = null, bool checkVisibility = true)
|
||||||
{
|
{
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user