Unstable v0.15.17.0 (Hex is out of town edition)
This commit is contained in:
@@ -63,7 +63,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
foreach (var ic in character.MemState[0].SelectedItem.Components)
|
foreach (var ic in character.MemState[0].SelectedItem.Components)
|
||||||
{
|
{
|
||||||
if (ic.CanBeSelected) ic.Select(character);
|
if (ic.CanBeSelected)
|
||||||
|
{
|
||||||
|
ic.Select(character);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
character.SelectedConstruction = character.MemState[0].SelectedItem;
|
character.SelectedConstruction = character.MemState[0].SelectedItem;
|
||||||
@@ -98,6 +101,16 @@ namespace Barotrauma
|
|||||||
if (distSqrd > 10.0f || !character.CanMove)
|
if (distSqrd > 10.0f || !character.CanMove)
|
||||||
{
|
{
|
||||||
Collider.TargetRotation = newRotation;
|
Collider.TargetRotation = newRotation;
|
||||||
|
if (distSqrd > 10.0f)
|
||||||
|
{
|
||||||
|
//teleported very far - see if we need to move to another sub
|
||||||
|
Hull serverHull = Hull.FindHull(ConvertUnits.ToDisplayUnits(newPosition), CurrentHull, newPosition.Y < lowestSubPos);
|
||||||
|
if (currentHull != null && serverHull != null && serverHull.Submarine != currentHull.Submarine)
|
||||||
|
{
|
||||||
|
character.Submarine = serverHull.Submarine;
|
||||||
|
character.CurrentHull = CurrentHull = serverHull;
|
||||||
|
}
|
||||||
|
}
|
||||||
SetPosition(newPosition, lerp: distSqrd < 5.0f, ignorePlatforms: false);
|
SetPosition(newPosition, lerp: distSqrd < 5.0f, ignorePlatforms: false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -194,7 +207,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (character.SelectedConstruction != serverPos.SelectedItem)
|
if (character.SelectedConstruction != serverPos.SelectedItem)
|
||||||
{
|
{
|
||||||
serverPos.SelectedItem.TryInteract(character, true, true);
|
serverPos.SelectedItem.TryInteract(character, ignoreRequiredItems: true, forceSelectKey: true);
|
||||||
}
|
}
|
||||||
character.SelectedConstruction = serverPos.SelectedItem;
|
character.SelectedConstruction = serverPos.SelectedItem;
|
||||||
}
|
}
|
||||||
@@ -448,8 +461,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Failed to draw a ragdoll, limbs have been removed. Character: \"" + character.Name + "\", removed: " + character.Removed + "\n" + Environment.StackTrace.CleanupStackTrace());
|
DebugConsole.ThrowError("Failed to draw a ragdoll, limbs have been removed. Character: \"" + character.Name + "\", removed: " + character.Removed + "\n" + Environment.StackTrace.CleanupStackTrace());
|
||||||
GameAnalyticsManager.AddErrorEventOnce("Ragdoll.Draw:LimbsRemoved",
|
GameAnalyticsManager.AddErrorEventOnce("Ragdoll.Draw:LimbsRemoved",
|
||||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
GameAnalyticsManager.ErrorSeverity.Error,
|
||||||
"Failed to draw a ragdoll, limbs have been removed. Character: \"" + character.Name + "\", removed: " + character.Removed + "\n" + Environment.StackTrace.CleanupStackTrace());
|
"Failed to draw a ragdoll, limbs have been removed. Character: \"" + character.SpeciesName + "\", removed: " + character.Removed + "\n" + Environment.StackTrace.CleanupStackTrace());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -460,12 +473,17 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
float depthOffset = GetDepthOffset();
|
float depthOffset = GetDepthOffset();
|
||||||
|
if (!MathUtils.NearlyEqual(depthOffset, 0.0f))
|
||||||
|
{
|
||||||
|
foreach (Limb limb in limbs) { limb.ActiveSprite.Depth += depthOffset; }
|
||||||
|
}
|
||||||
for (int i = 0; i < limbs.Length; i++)
|
for (int i = 0; i < limbs.Length; i++)
|
||||||
{
|
{
|
||||||
var limb = inversedLimbDrawOrder[i];
|
inversedLimbDrawOrder[i].Draw(spriteBatch, cam, color);
|
||||||
if (depthOffset != 0.0f) { limb.ActiveSprite.Depth += depthOffset; }
|
}
|
||||||
limb.Draw(spriteBatch, cam, color);
|
if (!MathUtils.NearlyEqual(depthOffset, 0.0f))
|
||||||
if (depthOffset != 0.0f) { limb.ActiveSprite.Depth -= depthOffset; }
|
{
|
||||||
|
foreach (Limb limb in limbs) { limb.ActiveSprite.Depth -= depthOffset; }
|
||||||
}
|
}
|
||||||
LimbJoints.ForEach(j => j.Draw(spriteBatch));
|
LimbJoints.ForEach(j => j.Draw(spriteBatch));
|
||||||
}
|
}
|
||||||
@@ -486,7 +504,14 @@ namespace Barotrauma
|
|||||||
if (character.WorldPosition.X < character.SelectedConstruction.WorldPosition.X)
|
if (character.WorldPosition.X < character.SelectedConstruction.WorldPosition.X)
|
||||||
{
|
{
|
||||||
//at the left side of the ladder, needs to be drawn in front of the rungs
|
//at the left side of the ladder, needs to be drawn in front of the rungs
|
||||||
depthOffset = Math.Max(ladder.BackgroundSpriteDepth - 0.01f - maxDepth, 0.0f);
|
if (maxDepth > ladder.BackgroundSpriteDepth)
|
||||||
|
{
|
||||||
|
depthOffset = Math.Max(ladder.BackgroundSpriteDepth - 0.01f - maxDepth, 0.0f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
depthOffset = Math.Max(ladder.Item.GetDrawDepth() + 0.0001f - minDepth, -minDepth);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -305,9 +305,9 @@ namespace Barotrauma
|
|||||||
case 0: //NetEntityEvent.Type.InventoryState
|
case 0: //NetEntityEvent.Type.InventoryState
|
||||||
if (Inventory == null)
|
if (Inventory == null)
|
||||||
{
|
{
|
||||||
string errorMsg = "Received an inventory update message for an entity with no inventory (" + Name + ", removed: " + Removed + ")";
|
string errorMsg = "Received an inventory update message for an entity with no inventory ([name], removed: " + Removed + ")";
|
||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg.Replace("[name]", Name));
|
||||||
GameAnalyticsManager.AddErrorEventOnce("CharacterNetworking.ClientRead:NoInventory" + ID, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("CharacterNetworking.ClientRead:NoInventory" + ID, GameAnalyticsManager.ErrorSeverity.Error, errorMsg.Replace("[name]", SpeciesName));
|
||||||
|
|
||||||
//read anyway to prevent messing up reading the rest of the message
|
//read anyway to prevent messing up reading the rest of the message
|
||||||
_ = msg.ReadUInt16();
|
_ = msg.ReadUInt16();
|
||||||
@@ -651,7 +651,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
string errorMsg = $"Error in CharacterNetworking.ReadStatus: affliction not found ({afflictionName})";
|
string errorMsg = $"Error in CharacterNetworking.ReadStatus: affliction not found ({afflictionName})";
|
||||||
causeOfDeathType = CauseOfDeathType.Unknown;
|
causeOfDeathType = CauseOfDeathType.Unknown;
|
||||||
GameAnalyticsManager.AddErrorEventOnce("CharacterNetworking.ReadStatus:AfflictionIndexOutOfBounts", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("CharacterNetworking.ReadStatus:AfflictionIndexOutOfBounts", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -682,7 +682,7 @@ namespace Barotrauma
|
|||||||
if (severedJointIndex < 0 || severedJointIndex >= AnimController.LimbJoints.Length)
|
if (severedJointIndex < 0 || severedJointIndex >= AnimController.LimbJoints.Length)
|
||||||
{
|
{
|
||||||
string errorMsg = $"Error in CharacterNetworking.ReadStatus: severed joint index out of bounds (index: {severedJointIndex}, joint count: {AnimController.LimbJoints.Length})";
|
string errorMsg = $"Error in CharacterNetworking.ReadStatus: severed joint index out of bounds (index: {severedJointIndex}, joint count: {AnimController.LimbJoints.Length})";
|
||||||
GameAnalyticsManager.AddErrorEventOnce("CharacterNetworking.ReadStatus:JointIndexOutOfBounts", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("CharacterNetworking.ReadStatus:JointIndexOutOfBounts", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -453,13 +453,14 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
case Alignment.Left:
|
case Alignment.Left:
|
||||||
healthWindow.RectTransform.SetPosition(Anchor.BottomLeft);
|
healthWindow.RectTransform.SetPosition(Anchor.BottomLeft);
|
||||||
|
healthWindow.RectTransform.AbsoluteOffset = new Point(HUDLayoutSettings.InventoryAreaLower.X, screenResolution.Y - HUDLayoutSettings.ChatBoxArea.Y + HUDLayoutSettings.Padding);
|
||||||
break;
|
break;
|
||||||
case Alignment.Right:
|
case Alignment.Right:
|
||||||
healthWindow.RectTransform.SetPosition(Anchor.BottomRight);
|
healthWindow.RectTransform.SetPosition(Anchor.BottomRight);
|
||||||
|
healthWindow.RectTransform.AbsoluteOffset = new Point(HUDLayoutSettings.Padding, screenResolution.Y - HUDLayoutSettings.ChatBoxArea.Y + HUDLayoutSettings.Padding);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
healthWindow.RectTransform.AbsoluteOffset = new Point(HUDLayoutSettings.Padding, screenResolution.Y - HUDLayoutSettings.ChatBoxArea.Y + HUDLayoutSettings.Padding);
|
|
||||||
healthWindow.RectTransform.RecalculateChildren(false);
|
healthWindow.RectTransform.RecalculateChildren(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -648,8 +649,9 @@ namespace Barotrauma
|
|||||||
grainColor = oxygenLowGrainColor;
|
grainColor = oxygenLowGrainColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Affliction affliction in afflictions)
|
foreach (KeyValuePair<Affliction, LimbHealth> kvp in afflictions)
|
||||||
{
|
{
|
||||||
|
var affliction = kvp.Key;
|
||||||
distortStrength = Math.Max(distortStrength, affliction.GetScreenDistortStrength());
|
distortStrength = Math.Max(distortStrength, affliction.GetScreenDistortStrength());
|
||||||
blurStrength = Math.Max(blurStrength, affliction.GetScreenBlurStrength());
|
blurStrength = Math.Max(blurStrength, affliction.GetScreenBlurStrength());
|
||||||
radialDistortStrength = Math.Max(radialDistortStrength, affliction.GetRadialDistortStrength());
|
radialDistortStrength = Math.Max(radialDistortStrength, affliction.GetRadialDistortStrength());
|
||||||
@@ -662,16 +664,6 @@ namespace Barotrauma
|
|||||||
grainColor = Color.Lerp(grainColor, afflictionGrainColor, (float)Math.Pow(1.0f - oxygenLowStrength, 2));
|
grainColor = Color.Lerp(grainColor, afflictionGrainColor, (float)Math.Pow(1.0f - oxygenLowStrength, 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (LimbHealth limbHealth in limbHealths)
|
|
||||||
{
|
|
||||||
foreach (Affliction affliction in limbHealth.Afflictions)
|
|
||||||
{
|
|
||||||
distortStrength = Math.Max(distortStrength, affliction.GetScreenDistortStrength());
|
|
||||||
blurStrength = Math.Max(blurStrength, affliction.GetScreenBlurStrength());
|
|
||||||
radialDistortStrength = Math.Max(radialDistortStrength, affliction.GetRadialDistortStrength());
|
|
||||||
chromaticAberrationStrength = Math.Max(chromaticAberrationStrength, affliction.GetChromaticAberrationStrength());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Character.RadialDistortStrength = radialDistortStrength;
|
Character.RadialDistortStrength = radialDistortStrength;
|
||||||
Character.ChromaticAberrationStrength = chromaticAberrationStrength;
|
Character.ChromaticAberrationStrength = chromaticAberrationStrength;
|
||||||
@@ -777,7 +769,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
// If no limb is selected or highlighted, select the one with the most critical afflictions.
|
// If no limb is selected or highlighted, select the one with the most critical afflictions.
|
||||||
var affliction = SortAfflictionsBySeverity(GetAllAfflictions(a => a.Prefab.IndicatorLimb != LimbType.None)).FirstOrDefault();
|
var affliction = SortAfflictionsBySeverity(GetAllAfflictions(a => a.Prefab.IndicatorLimb != LimbType.None)).FirstOrDefault();
|
||||||
if (affliction.DamagePerSecond > 0 || affliction.Strength > 0)
|
if (affliction != null && (affliction.DamagePerSecond > 0 || affliction.Strength > 0))
|
||||||
{
|
{
|
||||||
var limbHealth = GetMatchingLimbHealth(affliction);
|
var limbHealth = GetMatchingLimbHealth(affliction);
|
||||||
if (limbHealth != null)
|
if (limbHealth != null)
|
||||||
@@ -788,7 +780,7 @@ namespace Barotrauma
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If no affliction is critical, select the limb which has most damage.
|
// If no affliction is critical, select the limb which has most damage.
|
||||||
var limbHealth = limbHealths.OrderByDescending(l => l.TotalDamage).FirstOrDefault();
|
var limbHealth = limbHealths.OrderByDescending(l => GetTotalDamage(l)).FirstOrDefault();
|
||||||
selectedLimbIndex = limbHealths.IndexOf(limbHealth);
|
selectedLimbIndex = limbHealths.IndexOf(limbHealth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -971,8 +963,9 @@ namespace Barotrauma
|
|||||||
UpdateAlignment();
|
UpdateAlignment();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Affliction affliction in afflictions)
|
foreach (KeyValuePair<Affliction, LimbHealth> kvp in afflictions)
|
||||||
{
|
{
|
||||||
|
var affliction = kvp.Key;
|
||||||
if (affliction.Prefab.AfflictionOverlay != null)
|
if (affliction.Prefab.AfflictionOverlay != null)
|
||||||
{
|
{
|
||||||
Sprite ScreenAfflictionOverlay = affliction.Prefab.AfflictionOverlay;
|
Sprite ScreenAfflictionOverlay = affliction.Prefab.AfflictionOverlay;
|
||||||
@@ -984,7 +977,7 @@ namespace Barotrauma
|
|||||||
float damageOverlayAlpha = DamageOverlayTimer;
|
float damageOverlayAlpha = DamageOverlayTimer;
|
||||||
if (Vitality < MaxVitality * 0.1f)
|
if (Vitality < MaxVitality * 0.1f)
|
||||||
{
|
{
|
||||||
damageOverlayAlpha = Math.Max(1.0f - (Vitality / maxVitality * 10.0f), damageOverlayAlpha);
|
damageOverlayAlpha = Math.Max(1.0f - (Vitality / UnmodifiedMaxVitality * 10.0f), damageOverlayAlpha);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1159,18 +1152,34 @@ namespace Barotrauma
|
|||||||
afflictionIconContainer.Content.ClearChildren();
|
afflictionIconContainer.Content.ClearChildren();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var currentAfflictions = GetMatchingAfflictions(selectedLimb, a => a.ShouldShowIcon(Character));
|
|
||||||
if (currentAfflictions.Any(a => !displayedAfflictions.Any(d => d.affliction == a)) ||
|
if (afflictionsDirty())
|
||||||
displayedAfflictions.Any(a => !currentAfflictions.Contains(a.affliction)))
|
|
||||||
{
|
{
|
||||||
|
var currentAfflictions = afflictions.Where(a => a.Value == selectedLimb && a.Key.ShouldShowIcon(Character)).Select(a => a.Key);
|
||||||
CreateAfflictionInfos(currentAfflictions);
|
CreateAfflictionInfos(currentAfflictions);
|
||||||
CreateRecommendedTreatments();
|
CreateRecommendedTreatments();
|
||||||
}
|
}
|
||||||
//update recommended treatments if the strength of some displayed affliction has changed by > 1
|
//update recommended treatments if the strength of some displayed affliction has changed by > 1
|
||||||
else if (displayedAfflictions.Any(d => Math.Abs(d.strength - currentAfflictions.First(a => a == d.affliction).Strength) > 1.0f))
|
else if (displayedAfflictions.Any(d => Math.Abs(d.strength - d.affliction.Strength) > 1.0f))
|
||||||
{
|
{
|
||||||
CreateRecommendedTreatments();
|
CreateRecommendedTreatments();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool afflictionsDirty()
|
||||||
|
{
|
||||||
|
//not displaying one of the current afflictions -> dirty
|
||||||
|
foreach (KeyValuePair<Affliction, LimbHealth> kvp in afflictions)
|
||||||
|
{
|
||||||
|
if (kvp.Value != selectedLimb || !kvp.Key.ShouldShowIcon(Character)) { continue; }
|
||||||
|
if (!displayedAfflictions.Any(d => d.affliction == kvp.Key)) { return true; }
|
||||||
|
}
|
||||||
|
//displaying an affliction we no longer have -> dirty
|
||||||
|
foreach ((Affliction affliction, float strength) in displayedAfflictions)
|
||||||
|
{
|
||||||
|
if (!afflictions.Any(a => a.Key == affliction)) { return true; }
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateAfflictionInfos(IEnumerable<Affliction> afflictions)
|
private void CreateAfflictionInfos(IEnumerable<Affliction> afflictions)
|
||||||
@@ -1604,7 +1613,7 @@ namespace Barotrauma
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (LimbHealth limbHealth in limbHealths)
|
foreach (LimbHealth limbHealth in limbHealths)
|
||||||
{
|
{
|
||||||
if (limbHealth.IndicatorSprite == null) continue;
|
if (limbHealth.IndicatorSprite == null) { continue; }
|
||||||
|
|
||||||
float scale = Math.Min(drawArea.Width / (float)limbHealth.IndicatorSprite.SourceRect.Width, drawArea.Height / (float)limbHealth.IndicatorSprite.SourceRect.Height);
|
float scale = Math.Min(drawArea.Width / (float)limbHealth.IndicatorSprite.SourceRect.Width, drawArea.Height / (float)limbHealth.IndicatorSprite.SourceRect.Height);
|
||||||
|
|
||||||
@@ -1623,6 +1632,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static readonly List<Affliction> afflictionsDisplayedOnLimb = new List<Affliction>();
|
||||||
private void DrawHealthWindow(SpriteBatch spriteBatch, Rectangle drawArea, bool allowHighlight)
|
private void DrawHealthWindow(SpriteBatch spriteBatch, Rectangle drawArea, bool allowHighlight)
|
||||||
{
|
{
|
||||||
if (Character.Removed) { return; }
|
if (Character.Removed) { return; }
|
||||||
@@ -1633,21 +1643,32 @@ namespace Barotrauma
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (LimbHealth limbHealth in limbHealths)
|
foreach (LimbHealth limbHealth in limbHealths)
|
||||||
{
|
{
|
||||||
if (limbHealth.IndicatorSprite == null) continue;
|
if (limbHealth.IndicatorSprite == null) { continue; }
|
||||||
|
|
||||||
Rectangle limbEffectiveArea = new Rectangle(limbHealth.IndicatorSprite.SourceRect.X + limbHealth.HighlightArea.X,
|
Rectangle limbEffectiveArea = new Rectangle(limbHealth.IndicatorSprite.SourceRect.X + limbHealth.HighlightArea.X,
|
||||||
limbHealth.IndicatorSprite.SourceRect.Y + limbHealth.HighlightArea.Y,
|
limbHealth.IndicatorSprite.SourceRect.Y + limbHealth.HighlightArea.Y,
|
||||||
limbHealth.HighlightArea.Width,
|
limbHealth.HighlightArea.Width,
|
||||||
limbHealth.HighlightArea.Height);
|
limbHealth.HighlightArea.Height);
|
||||||
|
|
||||||
float damageLerp = limbHealth.TotalDamage > 0.0f ? MathHelper.Lerp(0.2f, 1.0f, limbHealth.TotalDamage / 100.0f) : 0.0f;
|
float totalDamage = GetTotalDamage(limbHealth);
|
||||||
|
|
||||||
var tempAfflictions = GetMatchingAfflictions(limbHealth, a => true);
|
float damageLerp = totalDamage > 0.0f ? MathHelper.Lerp(0.2f, 1.0f, totalDamage / 100.0f) : 0.0f;
|
||||||
|
|
||||||
float negativeEffect = tempAfflictions.Where(a => !a.Prefab.IsBuff && a.ShouldShowIcon(Character)).Sum(a => a.Strength);
|
float negativeEffect = 0.0f, positiveEffect = 0.0f;
|
||||||
//float negativeMaxEffect = tempAfflictions.Where(a => !a.Prefab.IsBuff).Sum(a => a.Prefab.MaxStrength);
|
foreach (KeyValuePair<Affliction, LimbHealth> kvp in afflictions)
|
||||||
float positiveEffect = tempAfflictions.Where(a => a.Prefab.IsBuff && a.ShouldShowIcon(Character)).Sum(a => a.Strength * 0.2f);
|
{
|
||||||
//float positiveMaxEffect = tempAfflictions.Where(a => a.Prefab.IsBuff).Sum(a => a.Prefab.MaxStrength);
|
if (kvp.Value != limbHealth) { continue; }
|
||||||
|
var affliction = kvp.Key;
|
||||||
|
if (!affliction.ShouldShowIcon(Character)) { continue; }
|
||||||
|
if (!affliction.Prefab.IsBuff)
|
||||||
|
{
|
||||||
|
negativeEffect += affliction.Strength;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
positiveEffect += affliction.Strength * 0.2f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
float midPoint = (float)limbEffectiveArea.Center.Y / (float)limbHealth.IndicatorSprite.Texture.Height;
|
float midPoint = (float)limbEffectiveArea.Center.Y / (float)limbHealth.IndicatorSprite.Texture.Height;
|
||||||
float fadeDist = 0.6f * (float)limbEffectiveArea.Height / (float)limbHealth.IndicatorSprite.Texture.Height;
|
float fadeDist = 0.6f * (float)limbEffectiveArea.Height / (float)limbHealth.IndicatorSprite.Texture.Height;
|
||||||
@@ -1714,7 +1735,7 @@ namespace Barotrauma
|
|||||||
drawArea.Width / (float)limbIndicatorOverlay.FrameSize.X,
|
drawArea.Width / (float)limbIndicatorOverlay.FrameSize.X,
|
||||||
drawArea.Height / (float)limbIndicatorOverlay.FrameSize.Y);
|
drawArea.Height / (float)limbIndicatorOverlay.FrameSize.Y);
|
||||||
|
|
||||||
int frame = 0;
|
int frame;
|
||||||
int frameCount = 17;
|
int frameCount = 17;
|
||||||
if (limbIndicatorOverlayAnimState >= frameCount * 2) limbIndicatorOverlayAnimState = 0.0f;
|
if (limbIndicatorOverlayAnimState >= frameCount * 2) limbIndicatorOverlayAnimState = 0.0f;
|
||||||
if (limbIndicatorOverlayAnimState < frameCount)
|
if (limbIndicatorOverlayAnimState < frameCount)
|
||||||
@@ -1758,14 +1779,28 @@ namespace Barotrauma
|
|||||||
i = 0;
|
i = 0;
|
||||||
foreach (LimbHealth limbHealth in limbHealths)
|
foreach (LimbHealth limbHealth in limbHealths)
|
||||||
{
|
{
|
||||||
IEnumerable<Affliction> thisAfflictions = limbHealth.Afflictions.Where(a => a.ShouldShowIcon(Character));
|
bool shouldDisplayAffliction(KeyValuePair<Affliction, LimbHealth> kvp, LimbHealth limbHealth)
|
||||||
thisAfflictions = thisAfflictions.Concat(afflictions.Where(a =>
|
|
||||||
{
|
{
|
||||||
Limb indicatorLimb = Character.AnimController.GetLimb(a.Prefab.IndicatorLimb);
|
if (!kvp.Key.ShouldShowIcon(Character)) { return false; }
|
||||||
return indicatorLimb != null && indicatorLimb.HealthIndex == i && a.ShouldShowIcon(Character);
|
if (kvp.Value == limbHealth)
|
||||||
}));
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (kvp.Value == null)
|
||||||
|
{
|
||||||
|
Limb indicatorLimb = Character.AnimController.GetLimb(kvp.Key.Prefab.IndicatorLimb);
|
||||||
|
return indicatorLimb != null && indicatorLimb.HealthIndex == i;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (thisAfflictions.Count() <= 0) { i++; continue; }
|
afflictionsDisplayedOnLimb.Clear();
|
||||||
|
foreach (var affliction in afflictions)
|
||||||
|
{
|
||||||
|
if (shouldDisplayAffliction(affliction, limbHealth)) { afflictionsDisplayedOnLimb.Add(affliction.Key); }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!afflictionsDisplayedOnLimb.Any()) { i++; continue; }
|
||||||
if (limbHealth.IndicatorSprite == null) { continue; }
|
if (limbHealth.IndicatorSprite == null) { continue; }
|
||||||
|
|
||||||
float scale = Math.Min(drawArea.Width / (float)limbHealth.IndicatorSprite.SourceRect.Width, drawArea.Height / (float)limbHealth.IndicatorSprite.SourceRect.Height);
|
float scale = Math.Min(drawArea.Width / (float)limbHealth.IndicatorSprite.SourceRect.Width, drawArea.Height / (float)limbHealth.IndicatorSprite.SourceRect.Height);
|
||||||
@@ -1776,12 +1811,12 @@ namespace Barotrauma
|
|||||||
Vector2 iconPos = highlightArea.Center.ToVector2();
|
Vector2 iconPos = highlightArea.Center.ToVector2();
|
||||||
|
|
||||||
//Affliction mostSevereAffliction = thisAfflictions.FirstOrDefault(a => !a.Prefab.IsBuff && !thisAfflictions.Any(a2 => !a2.Prefab.IsBuff && a2.Strength > a.Strength)) ?? thisAfflictions.FirstOrDefault();
|
//Affliction mostSevereAffliction = thisAfflictions.FirstOrDefault(a => !a.Prefab.IsBuff && !thisAfflictions.Any(a2 => !a2.Prefab.IsBuff && a2.Strength > a.Strength)) ?? thisAfflictions.FirstOrDefault();
|
||||||
Affliction mostSevereAffliction = SortAfflictionsBySeverity(thisAfflictions, excludeBuffs: false).FirstOrDefault();
|
Affliction mostSevereAffliction = SortAfflictionsBySeverity(afflictionsDisplayedOnLimb, excludeBuffs: false).FirstOrDefault();
|
||||||
if (mostSevereAffliction != null) { DrawLimbAfflictionIcon(spriteBatch, mostSevereAffliction, iconScale, ref iconPos); }
|
if (mostSevereAffliction != null) { DrawLimbAfflictionIcon(spriteBatch, mostSevereAffliction, iconScale, ref iconPos); }
|
||||||
|
|
||||||
if (thisAfflictions.Count() > 1)
|
if (afflictionsDisplayedOnLimb.Count() > 1)
|
||||||
{
|
{
|
||||||
string additionalAfflictionCount = $"+{thisAfflictions.Count() - 1}";
|
string additionalAfflictionCount = $"+{afflictionsDisplayedOnLimb.Count() - 1}";
|
||||||
Vector2 displace = GUI.SubHeadingFont.MeasureString(additionalAfflictionCount);
|
Vector2 displace = GUI.SubHeadingFont.MeasureString(additionalAfflictionCount);
|
||||||
GUI.SubHeadingFont.DrawString(spriteBatch, additionalAfflictionCount, iconPos + new Vector2(displace.X * 1.1f, -displace.Y * 0.45f), Color.Black * 0.75f);
|
GUI.SubHeadingFont.DrawString(spriteBatch, additionalAfflictionCount, iconPos + new Vector2(displace.X * 1.1f, -displace.Y * 0.45f), Color.Black * 0.75f);
|
||||||
GUI.SubHeadingFont.DrawString(spriteBatch, additionalAfflictionCount, iconPos + new Vector2(displace.X, -displace.Y * 0.5f), Color.White);
|
GUI.SubHeadingFont.DrawString(spriteBatch, additionalAfflictionCount, iconPos + new Vector2(displace.X, -displace.Y * 0.5f), Color.White);
|
||||||
@@ -1834,8 +1869,7 @@ namespace Barotrauma
|
|||||||
healthBarHolder.Visible = value;
|
healthBarHolder.Visible = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly List<(AfflictionPrefab afflictionPrefab, float strength)> newAfflictions = new List<(AfflictionPrefab afflictionPrefab, float strength)>();
|
private readonly List<(LimbHealth limb, AfflictionPrefab afflictionPrefab, float strength)> newAfflictions = new List<(LimbHealth limb, AfflictionPrefab afflictionPrefab, float strength)>();
|
||||||
private readonly List<(LimbHealth limb, AfflictionPrefab afflictionPrefab, float strength)> newLimbAfflictions = new List<(LimbHealth limb, AfflictionPrefab afflictionPrefab, float strength)>();
|
|
||||||
private readonly List<(AfflictionPrefab.PeriodicEffect effect, float timer)> newPeriodicEffects = new List<(AfflictionPrefab.PeriodicEffect effect, float timer)>();
|
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)
|
||||||
@@ -1865,47 +1899,9 @@ namespace Barotrauma
|
|||||||
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((afflictionPrefab.PeriodicEffects[j], periodicAfflictionTimer));
|
newPeriodicEffects.Add((afflictionPrefab.PeriodicEffects[j], periodicAfflictionTimer));
|
||||||
}
|
}
|
||||||
newAfflictions.Add((afflictionPrefab, afflictionStrength));
|
newAfflictions.Add((null, afflictionPrefab, afflictionStrength));
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Affliction affliction in afflictions)
|
|
||||||
{
|
|
||||||
//deactivate afflictions that weren't included in the network message
|
|
||||||
if (!newAfflictions.Any(a => a.afflictionPrefab == affliction.Prefab))
|
|
||||||
{
|
|
||||||
affliction.Strength = 0.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var (afflictionPrefab, strength) in newAfflictions)
|
|
||||||
{
|
|
||||||
Affliction existingAffliction = afflictions.Find(a => a.Prefab == afflictionPrefab);
|
|
||||||
if (existingAffliction == null)
|
|
||||||
{
|
|
||||||
existingAffliction = afflictionPrefab.Instantiate(strength);
|
|
||||||
afflictions.Add(existingAffliction);
|
|
||||||
}
|
|
||||||
existingAffliction.SetStrength(strength);
|
|
||||||
if (existingAffliction == stunAffliction)
|
|
||||||
{
|
|
||||||
Character.SetStun(existingAffliction.Strength, true, true);
|
|
||||||
}
|
|
||||||
foreach (var periodicEffect in newPeriodicEffects)
|
|
||||||
{
|
|
||||||
if (!existingAffliction.Prefab.PeriodicEffects.Contains(periodicEffect.effect)) { continue; }
|
|
||||||
//timer has wrapped around, apply the effect
|
|
||||||
if (periodicEffect.timer - existingAffliction.PeriodicEffectTimers[periodicEffect.effect] > periodicEffect.effect.MinInterval / 2)
|
|
||||||
{
|
|
||||||
existingAffliction.PeriodicEffectTimers[periodicEffect.effect] = periodicEffect.timer;
|
|
||||||
foreach (StatusEffect effect in periodicEffect.effect.StatusEffects)
|
|
||||||
{
|
|
||||||
existingAffliction.ApplyStatusEffect(ActionType.OnActive, effect, deltaTime: 1.0f, this, targetLimb: null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
newLimbAfflictions.Clear();
|
|
||||||
byte limbAfflictionCount = inc.ReadByte();
|
byte limbAfflictionCount = inc.ReadByte();
|
||||||
for (int i = 0; i < limbAfflictionCount; i++)
|
for (int i = 0; i < limbAfflictionCount; i++)
|
||||||
{
|
{
|
||||||
@@ -1931,43 +1927,50 @@ namespace Barotrauma
|
|||||||
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((afflictionPrefab.PeriodicEffects[j], periodicAfflictionTimer));
|
newPeriodicEffects.Add((afflictionPrefab.PeriodicEffects[j], periodicAfflictionTimer));
|
||||||
}
|
}
|
||||||
newLimbAfflictions.Add((limbHealths[limbIndex], afflictionPrefab, afflictionStrength));
|
newAfflictions.Add((limbHealths[limbIndex], afflictionPrefab, afflictionStrength));
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (LimbHealth limbHealth in limbHealths)
|
foreach (KeyValuePair<Affliction, LimbHealth> kvp in afflictions)
|
||||||
{
|
{
|
||||||
foreach (Affliction affliction in limbHealth.Afflictions)
|
//deactivate afflictions that weren't included in the network message
|
||||||
|
if (!newAfflictions.Any(a => kvp.Key.Prefab == a.afflictionPrefab && kvp.Value == a.limb))
|
||||||
{
|
{
|
||||||
//deactivate afflictions that weren't included in the network message
|
kvp.Key.Strength = 0.0f;
|
||||||
if (!newLimbAfflictions.Any(a => a.limb == limbHealth && a.afflictionPrefab == affliction.Prefab))
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var (limb, afflictionPrefab, strength) in newAfflictions)
|
||||||
|
{
|
||||||
|
Affliction existingAffliction = null;
|
||||||
|
foreach (KeyValuePair<Affliction, LimbHealth> kvp in afflictions)
|
||||||
|
{
|
||||||
|
if (kvp.Key.Prefab == afflictionPrefab && kvp.Value == limb)
|
||||||
{
|
{
|
||||||
affliction.Strength = 0.0f;
|
existingAffliction = kvp.Key;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (existingAffliction == null)
|
||||||
foreach (var (limb, afflictionPrefab, strength) in newLimbAfflictions)
|
|
||||||
{
|
{
|
||||||
if (limb != limbHealth) { continue; }
|
existingAffliction = afflictionPrefab.Instantiate(strength);
|
||||||
Affliction existingAffliction = limbHealth.Afflictions.Find(a => a.Prefab == afflictionPrefab);
|
afflictions.Add(existingAffliction, limb);
|
||||||
if (existingAffliction == null)
|
}
|
||||||
|
existingAffliction.SetStrength(strength);
|
||||||
|
if (existingAffliction == stunAffliction)
|
||||||
|
{
|
||||||
|
Character.SetStun(existingAffliction.Strength, true, true);
|
||||||
|
}
|
||||||
|
foreach (var periodicEffect in newPeriodicEffects)
|
||||||
|
{
|
||||||
|
if (!existingAffliction.Prefab.PeriodicEffects.Contains(periodicEffect.effect)) { continue; }
|
||||||
|
//timer has wrapped around, apply the effect
|
||||||
|
if (periodicEffect.timer - existingAffliction.PeriodicEffectTimers[periodicEffect.effect] > periodicEffect.effect.MinInterval / 2)
|
||||||
{
|
{
|
||||||
existingAffliction = afflictionPrefab.Instantiate(strength);
|
existingAffliction.PeriodicEffectTimers[periodicEffect.effect] = periodicEffect.timer;
|
||||||
limbHealth.Afflictions.Add(existingAffliction);
|
foreach (StatusEffect effect in periodicEffect.effect.StatusEffects)
|
||||||
}
|
|
||||||
existingAffliction.SetStrength(strength);
|
|
||||||
|
|
||||||
foreach (var periodicEffect in newPeriodicEffects)
|
|
||||||
{
|
|
||||||
if (!existingAffliction.Prefab.PeriodicEffects.Contains(periodicEffect.effect)) { continue; }
|
|
||||||
//timer has wrapped around, apply the effect
|
|
||||||
if (periodicEffect.timer - existingAffliction.PeriodicEffectTimers[periodicEffect.effect] > periodicEffect.effect.MinInterval / 2)
|
|
||||||
{
|
{
|
||||||
existingAffliction.PeriodicEffectTimers[periodicEffect.effect] = periodicEffect.timer;
|
Limb targetLimb = Character.AnimController.Limbs.FirstOrDefault(l => l.HealthIndex == limbHealths.IndexOf(limb));
|
||||||
foreach (StatusEffect effect in periodicEffect.effect.StatusEffects)
|
existingAffliction.ApplyStatusEffect(ActionType.OnActive, effect, deltaTime: 1.0f, this, targetLimb: targetLimb);
|
||||||
{
|
|
||||||
Limb targetLimb = Character.AnimController.Limbs.FirstOrDefault(l => l.HealthIndex == limbHealths.IndexOf(limb));
|
|
||||||
existingAffliction.ApplyStatusEffect(ActionType.OnActive, effect, deltaTime: 1.0f, this, targetLimb: targetLimb);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1985,14 +1988,13 @@ namespace Barotrauma
|
|||||||
|
|
||||||
limb.BurnOverlayStrength = 0.0f;
|
limb.BurnOverlayStrength = 0.0f;
|
||||||
limb.DamageOverlayStrength = 0.0f;
|
limb.DamageOverlayStrength = 0.0f;
|
||||||
if (limbHealths[limb.HealthIndex].Afflictions.Count == 0) continue;
|
foreach (KeyValuePair<Affliction, LimbHealth> kvp in afflictions)
|
||||||
foreach (Affliction a in limbHealths[limb.HealthIndex].Afflictions)
|
|
||||||
{
|
{
|
||||||
limb.BurnOverlayStrength += a.Strength / Math.Min(a.Prefab.MaxStrength, 100) * a.Prefab.BurnOverlayAlpha;
|
if (kvp.Value != limbHealths[limb.HealthIndex]) { continue; }
|
||||||
limb.DamageOverlayStrength += a.Strength / Math.Min(a.Prefab.MaxStrength, 100) * a.Prefab.DamageOverlayAlpha;
|
var affliction = kvp.Key;
|
||||||
|
limb.BurnOverlayStrength += affliction.Strength / Math.Min(affliction.Prefab.MaxStrength, 100) * affliction.Prefab.BurnOverlayAlpha;
|
||||||
|
limb.DamageOverlayStrength += affliction.Strength / Math.Min(affliction.Prefab.MaxStrength, 100) * affliction.Prefab.DamageOverlayAlpha;
|
||||||
}
|
}
|
||||||
limb.BurnOverlayStrength /= limbHealths[limb.HealthIndex].Afflictions.Count;
|
|
||||||
limb.DamageOverlayStrength /= limbHealths[limb.HealthIndex].Afflictions.Count;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -553,6 +553,12 @@ namespace Barotrauma
|
|||||||
levelGenerationParams = LevelGenerationParams.LevelParams.FirstOrDefault(p => p.Identifier == levelGenerationIdentifier);
|
levelGenerationParams = LevelGenerationParams.LevelParams.FirstOrDefault(p => p.Identifier == levelGenerationIdentifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SubmarineInfo.SavedSubmarines.None(s => s.Name.ToLowerInvariant() == subName.ToLowerInvariant()))
|
||||||
|
{
|
||||||
|
ThrowError($"Cannot find a sub that matches the name \"{subName}\".");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
GameMain.MainMenuScreen.QuickStart(fixedSeed: false, subName, difficulty, levelGenerationParams);
|
GameMain.MainMenuScreen.QuickStart(fixedSeed: false, subName, difficulty, levelGenerationParams);
|
||||||
|
|
||||||
}, getValidArgs: () => new[] { SubmarineInfo.SavedSubmarines.Select(s => s.Name).Distinct().ToArray() }));
|
}, getValidArgs: () => new[] { SubmarineInfo.SavedSubmarines.Select(s => s.Name).Distinct().ToArray() }));
|
||||||
@@ -1461,10 +1467,11 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
foreach (ItemPrefab ingredientItemPrefab in ingredient.ItemPrefabs)
|
foreach (ItemPrefab ingredientItemPrefab in ingredient.ItemPrefabs)
|
||||||
{
|
{
|
||||||
NewMessage(" Its ingredient " + ingredientItemPrefab.Name + " has base cost " + ingredientItemPrefab.DefaultPrice.Price);
|
int defaultPrice = ingredientItemPrefab.DefaultPrice?.Price ?? 0;
|
||||||
totalPrice += ingredientItemPrefab.DefaultPrice.Price;
|
NewMessage(" Its ingredient " + ingredientItemPrefab.Name + " has base cost " + defaultPrice);
|
||||||
|
totalPrice += defaultPrice;
|
||||||
totalBestPrice += ingredientItemPrefab.GetMinPrice();
|
totalBestPrice += ingredientItemPrefab.GetMinPrice();
|
||||||
int basePrice = ingredientItemPrefab.DefaultPrice.Price;
|
int basePrice = defaultPrice;
|
||||||
foreach (KeyValuePair<string, PriceInfo> ingredientItemLocationPrice in ingredientItemPrefab.GetBuyPricesUnder())
|
foreach (KeyValuePair<string, PriceInfo> ingredientItemLocationPrice in ingredientItemPrefab.GetBuyPricesUnder())
|
||||||
{
|
{
|
||||||
if (basePrice > ingredientItemLocationPrice.Value.Price)
|
if (basePrice > ingredientItemLocationPrice.Value.Price)
|
||||||
@@ -1630,7 +1637,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
var fabricationRecipe = fabricableItems.Find(f => f.TargetItem == parentItem);
|
var fabricationRecipe = fabricableItems.Find(f => f.TargetItem == parentItem);
|
||||||
int totalValue = 0;
|
int totalValue = 0;
|
||||||
NewMessage(parentItem.Name + " has the price " + parentItem.DefaultPrice.Price);
|
NewMessage(parentItem.Name + " has the price " + (parentItem.DefaultPrice?.Price ?? 0));
|
||||||
if (fabricationRecipe != null)
|
if (fabricationRecipe != null)
|
||||||
{
|
{
|
||||||
NewMessage(" It constructs from:");
|
NewMessage(" It constructs from:");
|
||||||
@@ -1639,8 +1646,9 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
foreach (ItemPrefab itemPrefab in requiredItem.ItemPrefabs)
|
foreach (ItemPrefab itemPrefab in requiredItem.ItemPrefabs)
|
||||||
{
|
{
|
||||||
NewMessage(" " + itemPrefab.Name + " has the price " + itemPrefab.DefaultPrice.Price);
|
int defaultPrice = itemPrefab.DefaultPrice?.Price ?? 0;
|
||||||
totalValue += itemPrefab.DefaultPrice.Price;
|
NewMessage(" " + itemPrefab.Name + " has the price " + defaultPrice);
|
||||||
|
totalValue += defaultPrice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NewMessage("Its total value was: " + totalValue);
|
NewMessage("Its total value was: " + totalValue);
|
||||||
@@ -1651,10 +1659,16 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
ItemPrefab itemPrefab =
|
ItemPrefab itemPrefab =
|
||||||
(MapEntityPrefab.Find(deconstructItem.ItemIdentifier, identifier: null, showErrorMessages: false) ??
|
(MapEntityPrefab.Find(deconstructItem.ItemIdentifier, identifier: null, showErrorMessages: false) ??
|
||||||
MapEntityPrefab.Find(null, identifier: itemNameOrId, showErrorMessages: false)) as ItemPrefab;
|
MapEntityPrefab.Find(null, identifier: deconstructItem.ItemIdentifier, showErrorMessages: false)) as ItemPrefab;
|
||||||
|
if (itemPrefab == null)
|
||||||
|
{
|
||||||
|
ThrowError($" Couldn't find deconstruct product \"{deconstructItem.ItemIdentifier}\"!");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
NewMessage(" " + itemPrefab.Name + " has the price " + itemPrefab.DefaultPrice.Price);
|
int defaultPrice = itemPrefab.DefaultPrice?.Price ?? 0;
|
||||||
totalValue += itemPrefab.DefaultPrice.Price;
|
NewMessage(" " + itemPrefab.Name + " has the price " + defaultPrice);
|
||||||
|
totalValue += defaultPrice;
|
||||||
}
|
}
|
||||||
NewMessage("Its deconstruct value was: " + totalValue);
|
NewMessage("Its deconstruct value was: " + totalValue);
|
||||||
|
|
||||||
@@ -2485,8 +2499,6 @@ namespace Barotrauma
|
|||||||
NewMessage("Resolution set to 0 x 0 (screen resolution will be used)", Color.Green);
|
NewMessage("Resolution set to 0 x 0 (screen resolution will be used)", Color.Green);
|
||||||
NewMessage("Fullscreen enabled", Color.Green);
|
NewMessage("Fullscreen enabled", Color.Green);
|
||||||
|
|
||||||
GameSettings.ShowUserStatisticsPrompt = true;
|
|
||||||
|
|
||||||
GameSettings.VerboseLogging = false;
|
GameSettings.VerboseLogging = false;
|
||||||
|
|
||||||
if (GameMain.Config.MasterServerUrl != "http://www.undertowgames.com/baromaster")
|
if (GameMain.Config.MasterServerUrl != "http://www.undertowgames.com/baromaster")
|
||||||
@@ -3162,7 +3174,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
string errorMsg = "Failed to spawn a submarine. Arguments: \"" + string.Join(" ", args) + "\".";
|
string errorMsg = "Failed to spawn a submarine. Arguments: \"" + string.Join(" ", args) + "\".";
|
||||||
ThrowError(errorMsg, e);
|
ThrowError(errorMsg, e);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("DebugConsole.SpawnSubmarine:Error", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg + '\n' + e.Message + '\n' + e.StackTrace.CleanupStackTrace());
|
GameAnalyticsManager.AddErrorEventOnce("DebugConsole.SpawnSubmarine:Error", GameAnalyticsManager.ErrorSeverity.Error, errorMsg + '\n' + e.Message + '\n' + e.StackTrace.CleanupStackTrace());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
() =>
|
() =>
|
||||||
|
|||||||
@@ -363,7 +363,7 @@ namespace Barotrauma
|
|||||||
OnSecondaryClicked = (_, o) =>
|
OnSecondaryClicked = (_, o) =>
|
||||||
{
|
{
|
||||||
if (!(o is Client client)) { return false; }
|
if (!(o is Client client)) { return false; }
|
||||||
GameMain.GameSession?.CrewManager?.CreateModerationContextMenu(PlayerInput.MousePosition.ToPoint(), client);
|
NetLobbyScreen.CreateModerationContextMenu(client);
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
Text = senderName
|
Text = senderName
|
||||||
@@ -397,6 +397,7 @@ namespace Barotrauma
|
|||||||
if (GameMain.NetLobbyScreen != null && GameMain.NetworkMember != null)
|
if (GameMain.NetLobbyScreen != null && GameMain.NetworkMember != null)
|
||||||
{
|
{
|
||||||
clickableArea.OnClick = GameMain.NetLobbyScreen.SelectPlayer;
|
clickableArea.OnClick = GameMain.NetLobbyScreen.SelectPlayer;
|
||||||
|
clickableArea.OnSecondaryClick = GameMain.NetLobbyScreen.ShowPlayerContextMenu;
|
||||||
}
|
}
|
||||||
msgText.ClickableAreas.Add(clickableArea);
|
msgText.ClickableAreas.Add(clickableArea);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public bool AllowMouseWheelScroll { get; set; } = true;
|
public bool AllowMouseWheelScroll { get; set; } = true;
|
||||||
|
|
||||||
|
public bool AllowArrowKeyScroll { get; set; } = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Scrolls the list smoothly
|
/// Scrolls the list smoothly
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -1254,10 +1256,16 @@ namespace Barotrauma
|
|||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
case Keys.Down:
|
case Keys.Down:
|
||||||
SelectNext();
|
if (!isHorizontal && AllowArrowKeyScroll) { SelectNext(); }
|
||||||
break;
|
break;
|
||||||
case Keys.Up:
|
case Keys.Up:
|
||||||
SelectPrevious();
|
if (!isHorizontal && AllowArrowKeyScroll) { SelectPrevious(); }
|
||||||
|
break;
|
||||||
|
case Keys.Left:
|
||||||
|
if (isHorizontal && AllowArrowKeyScroll) { SelectPrevious(); }
|
||||||
|
break;
|
||||||
|
case Keys.Right:
|
||||||
|
if (isHorizontal && AllowArrowKeyScroll) { SelectNext(); }
|
||||||
break;
|
break;
|
||||||
case Keys.Enter:
|
case Keys.Enter:
|
||||||
case Keys.Space:
|
case Keys.Space:
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
GameAnalyticsManager.AddErrorEventOnce(
|
GameAnalyticsManager.AddErrorEventOnce(
|
||||||
"GUIProgressBar.BarSize_setter",
|
"GUIProgressBar.BarSize_setter",
|
||||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
GameAnalyticsManager.ErrorSeverity.Error,
|
||||||
"Attempted to set the BarSize of a GUIProgressBar to an invalid value (" + value + ")\n" + Environment.StackTrace.CleanupStackTrace());
|
"Attempted to set the BarSize of a GUIProgressBar to an invalid value (" + value + ")\n" + Environment.StackTrace.CleanupStackTrace());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -105,7 +105,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
GameAnalyticsManager.AddErrorEventOnce(
|
GameAnalyticsManager.AddErrorEventOnce(
|
||||||
"GUIProgressBar.Draw:GetProgress",
|
"GUIProgressBar.Draw:GetProgress",
|
||||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
GameAnalyticsManager.ErrorSeverity.Error,
|
||||||
"ProgressGetter of a GUIProgressBar (" + ProgressGetter.Target.ToString() + " - " + ProgressGetter.Method.ToString() + ") returned an invalid value (" + newSize + ")\n" + Environment.StackTrace.CleanupStackTrace());
|
"ProgressGetter of a GUIProgressBar (" + ProgressGetter.Target.ToString() + " - " + ProgressGetter.Method.ToString() + ") returned an invalid value (" + newSize + ")\n" + Environment.StackTrace.CleanupStackTrace());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -276,6 +276,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public delegate void OnClickDelegate(GUITextBlock textBlock, ClickableArea area);
|
public delegate void OnClickDelegate(GUITextBlock textBlock, ClickableArea area);
|
||||||
public OnClickDelegate OnClick;
|
public OnClickDelegate OnClick;
|
||||||
|
public OnClickDelegate OnSecondaryClick;
|
||||||
}
|
}
|
||||||
public List<ClickableArea> ClickableAreas { get; private set; } = new List<ClickableArea>();
|
public List<ClickableArea> ClickableAreas { get; private set; } = new List<ClickableArea>();
|
||||||
|
|
||||||
@@ -528,7 +529,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
base.Update(deltaTime);
|
base.Update(deltaTime);
|
||||||
|
|
||||||
if (ClickableAreas.Any() && (GUI.MouseOn?.IsParentOf(this) ?? true))
|
if (ClickableAreas.Any() && ((GUI.MouseOn?.IsParentOf(this) ?? true) || GUI.MouseOn == this))
|
||||||
{
|
{
|
||||||
if (!Rect.Contains(PlayerInput.MousePosition)) { return; }
|
if (!Rect.Contains(PlayerInput.MousePosition)) { return; }
|
||||||
int index = GetCaretIndexFromScreenPos(PlayerInput.MousePosition);
|
int index = GetCaretIndexFromScreenPos(PlayerInput.MousePosition);
|
||||||
@@ -541,6 +542,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
clickableArea.OnClick?.Invoke(this, clickableArea);
|
clickableArea.OnClick?.Invoke(this, clickableArea);
|
||||||
}
|
}
|
||||||
|
if (PlayerInput.SecondaryMouseButtonClicked())
|
||||||
|
{
|
||||||
|
clickableArea.OnSecondaryClick?.Invoke(this, clickableArea);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -562,7 +562,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
frame.OnSecondaryClicked += (component, data) =>
|
frame.OnSecondaryClicked += (component, data) =>
|
||||||
{
|
{
|
||||||
GameMain.GameSession?.CrewManager?.CreateModerationContextMenu(PlayerInput.MousePosition.ToPoint(), client);
|
NetLobbyScreen.CreateModerationContextMenu(client);
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -917,7 +917,8 @@ namespace Barotrauma
|
|||||||
textBlock.ClickableAreas.Add(new GUITextBlock.ClickableArea()
|
textBlock.ClickableAreas.Add(new GUITextBlock.ClickableArea()
|
||||||
{
|
{
|
||||||
Data = data,
|
Data = data,
|
||||||
OnClick = GameMain.NetLobbyScreen.SelectPlayer
|
OnClick = GameMain.NetLobbyScreen.SelectPlayer,
|
||||||
|
OnSecondaryClick = GameMain.NetLobbyScreen.ShowPlayerContextMenu
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1486,12 +1487,13 @@ namespace Barotrauma
|
|||||||
experienceBar = new GUIProgressBar(new RectTransform(new Vector2(1f, 1f), experienceBarFrame.RectTransform, Anchor.CenterLeft),
|
experienceBar = new GUIProgressBar(new RectTransform(new Vector2(1f, 1f), experienceBarFrame.RectTransform, Anchor.CenterLeft),
|
||||||
barSize: controlledCharacter.Info.GetProgressTowardsNextLevel(), color: GUI.Style.Green)
|
barSize: controlledCharacter.Info.GetProgressTowardsNextLevel(), color: GUI.Style.Green)
|
||||||
{
|
{
|
||||||
IsHorizontal = true
|
IsHorizontal = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
experienceText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), experienceBarFrame.RectTransform, anchor: Anchor.Center), "", font: GUI.Font, textAlignment: Alignment.CenterRight)
|
experienceText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), experienceBarFrame.RectTransform, anchor: Anchor.Center), "", font: GUI.Font, textAlignment: Alignment.CenterRight)
|
||||||
{
|
{
|
||||||
Shadow = true
|
Shadow = true,
|
||||||
|
ToolTip = TextManager.Get("experiencetooltip")
|
||||||
};
|
};
|
||||||
|
|
||||||
talentPointText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), experienceLayout.RectTransform, anchor: Anchor.Center), "", font: GUI.SubHeadingFont, parseRichText: true, textAlignment: Alignment.CenterRight) { AutoScaleVertical = true };
|
talentPointText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), experienceLayout.RectTransform, anchor: Anchor.Center), "", font: GUI.SubHeadingFont, parseRichText: true, textAlignment: Alignment.CenterRight) { AutoScaleVertical = true };
|
||||||
@@ -1643,6 +1645,7 @@ namespace Barotrauma
|
|||||||
GameMain.Client.CreateEntityEvent(controlledCharacter, new object[] { NetEntityEvent.Type.UpdateTalents });
|
GameMain.Client.CreateEntityEvent(controlledCharacter, new object[] { NetEntityEvent.Type.UpdateTalents });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
selectedTalents = controlledCharacter.Info.GetUnlockedTalentsInTree().ToList();
|
||||||
UpdateTalentButtons();
|
UpdateTalentButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -846,23 +846,27 @@ namespace Barotrauma
|
|||||||
|
|
||||||
var currentOrPending = item.PendingItemSwap ?? item.Prefab;
|
var currentOrPending = item.PendingItemSwap ?? item.Prefab;
|
||||||
string name = currentOrPending.Name;
|
string name = currentOrPending.Name;
|
||||||
string quantityText = "";
|
string nameWithQuantity = "";
|
||||||
if (linkedItems.Count > 1)
|
if (linkedItems.Count > 1)
|
||||||
{
|
{
|
||||||
foreach (ItemPrefab distinctItem in linkedItems.Select(it => it.Prefab).Distinct())
|
foreach (ItemPrefab distinctItem in linkedItems.Select(it => it.Prefab).Distinct())
|
||||||
{
|
{
|
||||||
if (quantityText != string.Empty)
|
if (nameWithQuantity != string.Empty)
|
||||||
{
|
{
|
||||||
quantityText += ", ";
|
nameWithQuantity += ", ";
|
||||||
}
|
}
|
||||||
int count = linkedItems.Count(it => it.Prefab == distinctItem);
|
int count = linkedItems.Count(it => it.Prefab == distinctItem);
|
||||||
quantityText += distinctItem.Name;
|
nameWithQuantity += distinctItem.Name;
|
||||||
if (count > 1)
|
if (count > 1)
|
||||||
{
|
{
|
||||||
quantityText += " " + TextManager.GetWithVariable("campaignstore.quantity", "[amount]", count.ToString());
|
nameWithQuantity += " " + TextManager.GetWithVariable("campaignstore.quantity", "[amount]", count.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nameWithQuantity = name;
|
||||||
|
}
|
||||||
|
|
||||||
bool isOpen = false;
|
bool isOpen = false;
|
||||||
GUIButton toggleButton = new GUIButton(rectT(1f, 0.1f, parent.Content), text: string.Empty, style: "SlideDown")
|
GUIButton toggleButton = new GUIButton(rectT(1f, 0.1f, parent.Content), text: string.Empty, style: "SlideDown")
|
||||||
@@ -884,7 +888,7 @@ namespace Barotrauma
|
|||||||
new GUITextBlock(rectT(0.3f, 1f, buttonLayout), text: slotText, font: GUI.SubHeadingFont);
|
new GUITextBlock(rectT(0.3f, 1f, buttonLayout), text: slotText, font: GUI.SubHeadingFont);
|
||||||
GUILayoutGroup group = new GUILayoutGroup(rectT(0.7f, 1f, buttonLayout), isHorizontal: true) { Stretch = true };
|
GUILayoutGroup group = new GUILayoutGroup(rectT(0.7f, 1f, buttonLayout), isHorizontal: true) { Stretch = true };
|
||||||
|
|
||||||
string title = item.PendingItemSwap != null ? TextManager.GetWithVariable("upgrades.pendingitem", "[itemname]", name) : quantityText;
|
string title = item.PendingItemSwap != null ? TextManager.GetWithVariable("upgrades.pendingitem", "[itemname]", name) : nameWithQuantity;
|
||||||
GUITextBlock text = new GUITextBlock(rectT(0.7f, 1f, group), text: title, font: GUI.SubHeadingFont, textAlignment: Alignment.Right, parseRichText: true)
|
GUITextBlock text = new GUITextBlock(rectT(0.7f, 1f, group), text: title, font: GUI.SubHeadingFont, textAlignment: Alignment.Right, parseRichText: true)
|
||||||
{
|
{
|
||||||
TextColor = GUI.Style.Orange
|
TextColor = GUI.Style.Orange
|
||||||
@@ -907,7 +911,7 @@ namespace Barotrauma
|
|||||||
if (isUninstallPending) { canUninstall = false; }
|
if (isUninstallPending) { canUninstall = false; }
|
||||||
|
|
||||||
frames.Add(CreateUpgradeEntry(rectT(1f, 0.25f, parent.Content), currentOrPending.UpgradePreviewSprite,
|
frames.Add(CreateUpgradeEntry(rectT(1f, 0.25f, parent.Content), currentOrPending.UpgradePreviewSprite,
|
||||||
item.PendingItemSwap != null ? TextManager.GetWithVariable("upgrades.pendingitem", "[itemname]", name) : TextManager.GetWithVariable("upgrades.installeditem", "[itemname]", quantityText),
|
item.PendingItemSwap != null ? TextManager.GetWithVariable("upgrades.pendingitem", "[itemname]", name) : TextManager.GetWithVariable("upgrades.installeditem", "[itemname]", nameWithQuantity),
|
||||||
currentOrPending.Description,
|
currentOrPending.Description,
|
||||||
0, null, addBuyButton: canUninstall, addProgressBar: false, buttonStyle: "WeaponUninstallButton"));
|
0, null, addBuyButton: canUninstall, addProgressBar: false, buttonStyle: "WeaponUninstallButton"));
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using Barotrauma.IO;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
public static partial class GameAnalyticsManager
|
||||||
|
{
|
||||||
|
static partial void CreateConsentPrompt()
|
||||||
|
{
|
||||||
|
if (consentTextAvailable)
|
||||||
|
{
|
||||||
|
var background = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas), style: "GUIBackgroundBlocker");
|
||||||
|
var frame = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.7f), background.RectTransform, Anchor.Center) { MaxSize = new Point(800, int.MaxValue) });
|
||||||
|
|
||||||
|
var content = new GUILayoutGroup(new RectTransform(new Vector2(0.95f), frame.RectTransform, Anchor.Center))
|
||||||
|
{
|
||||||
|
Stretch = true,
|
||||||
|
AbsoluteSpacing = GUI.IntScale(15)
|
||||||
|
};
|
||||||
|
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), TextManager.Get("statisticsconsentheader"), font: GUI.SubHeadingFont, textColor: Color.White);
|
||||||
|
var mainText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), TextManager.Get("statisticsconsenttext"), wrap: true, parseRichText: true);
|
||||||
|
|
||||||
|
foreach (var data in mainText.RichTextData)
|
||||||
|
{
|
||||||
|
mainText.ClickableAreas.Add(new GUITextBlock.ClickableArea()
|
||||||
|
{
|
||||||
|
Data = data,
|
||||||
|
OnClick = (GUITextBlock component, GUITextBlock.ClickableArea area) =>
|
||||||
|
{
|
||||||
|
GameMain.Instance.ShowOpenUrlInWebBrowserPrompt("https://gameanalytics.com/privacy/");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
string privacyPolicyText = File.ReadAllText("daedalic_privacypolicy.txt");
|
||||||
|
var privacyPolicyBox = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform) { MaxSize = new Point(int.MaxValue, GUI.IntScale(200)) });
|
||||||
|
var privacyPolicy = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), privacyPolicyBox.Content.RectTransform), privacyPolicyText, wrap: true)
|
||||||
|
{
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
privacyPolicy.RectTransform.MinSize = new Point(0, (int)privacyPolicy.TextSize.Y);
|
||||||
|
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), TextManager.Get("statisticsconsentstatement"), wrap: true);
|
||||||
|
|
||||||
|
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), isHorizontal: true);
|
||||||
|
|
||||||
|
void buttonContainerSpacing(float width)
|
||||||
|
=> new GUIFrame(new RectTransform(new Vector2(width, 1.0f), buttonContainer.RectTransform), style: null);
|
||||||
|
|
||||||
|
buttonContainerSpacing(0.1f);
|
||||||
|
var yesBtn = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonContainer.RectTransform), TextManager.Get("Yes"));
|
||||||
|
yesBtn.OnClicked += (btn, userdata) =>
|
||||||
|
{
|
||||||
|
GUIMessageBox.MessageBoxes.Remove(background);
|
||||||
|
SetConsentInternal(Consent.Yes);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
yesBtn.Enabled = false;
|
||||||
|
|
||||||
|
IEnumerable<CoroutineStatus> enableAfterTime(WaitForSeconds time, params GUIComponent[] components)
|
||||||
|
{
|
||||||
|
yield return time;
|
||||||
|
foreach (var c in components)
|
||||||
|
{
|
||||||
|
c.Enabled = true;
|
||||||
|
}
|
||||||
|
yield return CoroutineStatus.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
buttonContainerSpacing(0.2f);
|
||||||
|
|
||||||
|
var noBtn = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonContainer.RectTransform), TextManager.Get("No"));
|
||||||
|
noBtn.OnClicked += (btn, userdata) =>
|
||||||
|
{
|
||||||
|
GUIMessageBox.MessageBoxes.Remove(background);
|
||||||
|
SetConsent(Consent.No);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
noBtn.Enabled = false;
|
||||||
|
|
||||||
|
CoroutineManager.StartCoroutine(enableAfterTime(new WaitForSeconds(0.3f), yesBtn, noBtn));
|
||||||
|
|
||||||
|
buttonContainerSpacing(0.1f);
|
||||||
|
|
||||||
|
buttonContainer.RectTransform.MinSize = new Point(0, yesBtn.RectTransform.MinSize.Y);
|
||||||
|
buttonContainer.RectTransform.MaxSize = new Point(int.MaxValue, yesBtn.RectTransform.MinSize.Y);
|
||||||
|
|
||||||
|
foreach (var child in content.Children)
|
||||||
|
{
|
||||||
|
if (child is GUITextBlock textBlock)
|
||||||
|
{
|
||||||
|
textBlock.RectTransform.MinSize = new Point(0, (int)textBlock.TextSize.Y);
|
||||||
|
textBlock.RectTransform.MaxSize = new Point(int.MaxValue, (int)textBlock.TextSize.Y + GUI.IntScale(15));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
frame.RectTransform.MaxSize = new Point(
|
||||||
|
frame.RectTransform.MaxSize.X,
|
||||||
|
(int)(content.Children.Sum(c => c.RectTransform.MaxSize.Y + content.AbsoluteSpacing) / content.RectTransform.RelativeSize.Y));
|
||||||
|
|
||||||
|
GUIMessageBox.MessageBoxes.Add(background);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//user statistics disabled by default if the prompt cannot be shown in the user's language
|
||||||
|
SetConsent(Consent.Unknown);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,6 @@ using System.Collections.Generic;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using GameAnalyticsSDK.Net;
|
|
||||||
using Barotrauma.IO;
|
using Barotrauma.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Barotrauma.Tutorials;
|
using Barotrauma.Tutorials;
|
||||||
@@ -384,51 +383,6 @@ namespace Barotrauma
|
|||||||
loadingCoroutine = CoroutineManager.StartCoroutine(Load(canLoadInSeparateThread), "Load", canLoadInSeparateThread);
|
loadingCoroutine = CoroutineManager.StartCoroutine(Load(canLoadInSeparateThread), "Load", canLoadInSeparateThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitUserStats()
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (GameSettings.ShowUserStatisticsPrompt)
|
|
||||||
{
|
|
||||||
if (TextManager.ContainsTag("statisticspromptheader") && TextManager.ContainsTag("statisticsprompttext"))
|
|
||||||
{
|
|
||||||
var userStatsPrompt = new GUIMessageBox(
|
|
||||||
TextManager.Get("statisticspromptheader"),
|
|
||||||
TextManager.Get("statisticsprompttext"),
|
|
||||||
new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
|
||||||
userStatsPrompt.Buttons[0].OnClicked += (btn, userdata) =>
|
|
||||||
{
|
|
||||||
GameSettings.ShowUserStatisticsPrompt = false;
|
|
||||||
GameSettings.SendUserStatistics = true;
|
|
||||||
GameAnalyticsManager.Init();
|
|
||||||
Config.SaveNewPlayerConfig();
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
userStatsPrompt.Buttons[0].OnClicked += userStatsPrompt.Close;
|
|
||||||
userStatsPrompt.Buttons[1].OnClicked += (btn, userdata) =>
|
|
||||||
{
|
|
||||||
GameSettings.ShowUserStatisticsPrompt = false;
|
|
||||||
GameSettings.SendUserStatistics = false;
|
|
||||||
Config.SaveNewPlayerConfig();
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
userStatsPrompt.Buttons[1].OnClicked += userStatsPrompt.Close;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//user statistics enabled by default if the prompt cannot be shown in the user's language
|
|
||||||
GameSettings.ShowUserStatisticsPrompt = false;
|
|
||||||
GameSettings.SendUserStatistics = true;
|
|
||||||
GameAnalyticsManager.Init();
|
|
||||||
Config.SaveNewPlayerConfig();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (GameSettings.SendUserStatistics)
|
|
||||||
{
|
|
||||||
GameAnalyticsManager.Init();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LoadingException : Exception
|
public class LoadingException : Exception
|
||||||
{
|
{
|
||||||
public LoadingException(Exception e) : base("Loading was interrupted due to an error.", innerException: e)
|
public LoadingException(Exception e) : base("Loading was interrupted due to an error.", innerException: e)
|
||||||
@@ -522,14 +476,9 @@ namespace Barotrauma
|
|||||||
DebugConsole.Log("Selected content packages: " + string.Join(", ", Config.AllEnabledPackages.Select(cp => cp.Name)));
|
DebugConsole.Log("Selected content packages: " + string.Join(", ", Config.AllEnabledPackages.Select(cp => cp.Name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG
|
GameAnalyticsManager.InitIfConsented();
|
||||||
GameSettings.ShowUserStatisticsPrompt = false;
|
|
||||||
GameSettings.SendUserStatistics = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
InitUserStats();
|
yield return CoroutineStatus.Running;
|
||||||
|
|
||||||
yield return CoroutineStatus.Running;
|
|
||||||
|
|
||||||
Debug.WriteLine("sounds");
|
Debug.WriteLine("sounds");
|
||||||
|
|
||||||
@@ -841,6 +790,8 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
NetworkMember?.Update((float)Timing.Step);
|
||||||
|
|
||||||
if (!hasLoaded && !CoroutineManager.IsCoroutineRunning(loadingCoroutine))
|
if (!hasLoaded && !CoroutineManager.IsCoroutineRunning(loadingCoroutine))
|
||||||
{
|
{
|
||||||
throw new LoadingException(loadingCoroutine.Exception);
|
throw new LoadingException(loadingCoroutine.Exception);
|
||||||
@@ -915,6 +866,11 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
gameSession.ToggleTabMenu();
|
gameSession.ToggleTabMenu();
|
||||||
}
|
}
|
||||||
|
else if (GUIMessageBox.VisibleBox as GUIMessageBox != null &&
|
||||||
|
GUIMessageBox.VisibleBox.UserData as string == "bugreporter")
|
||||||
|
{
|
||||||
|
((GUIMessageBox)GUIMessageBox.VisibleBox).Close();
|
||||||
|
}
|
||||||
else if (GUI.PauseMenuOpen)
|
else if (GUI.PauseMenuOpen)
|
||||||
{
|
{
|
||||||
GUI.TogglePauseMenu();
|
GUI.TogglePauseMenu();
|
||||||
@@ -999,11 +955,11 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetworkMember?.Update((float)Timing.Step);
|
||||||
|
|
||||||
GUI.Update((float)Timing.Step);
|
GUI.Update((float)Timing.Step);
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkMember?.Update((float)Timing.Step);
|
|
||||||
|
|
||||||
CoroutineManager.Update((float)Timing.Step, Paused ? 0.0f : (float)Timing.Step);
|
CoroutineManager.Update((float)Timing.Step, Paused ? 0.0f : (float)Timing.Step);
|
||||||
|
|
||||||
SteamManager.Update((float)Timing.Step);
|
SteamManager.Update((float)Timing.Step);
|
||||||
@@ -1123,6 +1079,10 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (GameSession != null)
|
if (GameSession != null)
|
||||||
{
|
{
|
||||||
|
double roundDuration = Timing.TotalTime - GameSession.RoundStartTime;
|
||||||
|
GameAnalyticsManager.AddProgressionEvent(GameAnalyticsManager.ProgressionStatus.Fail,
|
||||||
|
GameSession.GameMode?.Name ?? "none",
|
||||||
|
roundDuration);
|
||||||
if (Tutorial.Initialized)
|
if (Tutorial.Initialized)
|
||||||
{
|
{
|
||||||
((TutorialMode)GameSession.GameMode).Tutorial?.Stop();
|
((TutorialMode)GameSession.GameMode).Tutorial?.Stop();
|
||||||
@@ -1131,6 +1091,7 @@ namespace Barotrauma
|
|||||||
GUIMessageBox.CloseAll();
|
GUIMessageBox.CloseAll();
|
||||||
MainMenuScreen.Select();
|
MainMenuScreen.Select();
|
||||||
GameSession = null;
|
GameSession = null;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ShowCampaignDisclaimer(Action onContinue = null)
|
public void ShowCampaignDisclaimer(Action onContinue = null)
|
||||||
@@ -1254,7 +1215,7 @@ namespace Barotrauma
|
|||||||
DebugConsole.ThrowError("Error while cleaning unnecessary save files", e);
|
DebugConsole.ThrowError("Error while cleaning unnecessary save files", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameSettings.SendUserStatistics) { GameAnalytics.OnQuit(); }
|
if (GameAnalyticsManager.SendUserStatistics) { GameAnalyticsManager.ShutDown(); }
|
||||||
if (GameSettings.SaveDebugConsoleLogs || GameSettings.VerboseLogging) { DebugConsole.SaveLogs(); }
|
if (GameSettings.SaveDebugConsoleLogs || GameSettings.VerboseLogging) { DebugConsole.SaveLogs(); }
|
||||||
|
|
||||||
base.OnExiting(sender, args);
|
base.OnExiting(sender, args);
|
||||||
|
|||||||
@@ -330,7 +330,7 @@ namespace Barotrauma
|
|||||||
if (data == null) { return false; }
|
if (data == null) { return false; }
|
||||||
if (GameMain.NetworkMember?.ConnectedClients?.Find(c => c.Character == data) is Client client)
|
if (GameMain.NetworkMember?.ConnectedClients?.Find(c => c.Character == data) is Client client)
|
||||||
{
|
{
|
||||||
CreateModerationContextMenu(PlayerInput.MousePosition.ToPoint(), client);
|
NetLobbyScreen.CreateModerationContextMenu(client);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -789,7 +789,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else if (orderGiver != null)
|
else if (orderGiver != null)
|
||||||
{
|
{
|
||||||
OrderChatMessage msg = new OrderChatMessage(order, option, priority, order?.TargetSpatialEntity ?? order?.TargetItemComponent?.Item as ISpatialEntity, character, orderGiver);
|
OrderChatMessage msg = new OrderChatMessage(order, option, priority, order?.TargetSpatialEntity ?? order?.TargetItemComponent?.Item, character, orderGiver);
|
||||||
GameMain.Client?.SendChatMessage(msg);
|
GameMain.Client?.SendChatMessage(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -968,7 +968,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (!CanIssueOrders) { return false; }
|
if (!CanIssueOrders) { return false; }
|
||||||
var orderInfo = (OrderInfo)userData;
|
var orderInfo = (OrderInfo)userData;
|
||||||
SetCharacterOrder(character, orderInfo.Order, orderInfo.OrderOption, CharacterInfo.HighestManualOrderPriority, Character.Controlled);
|
int priority = GetManualOrderPriority(character, orderInfo.Order);
|
||||||
|
SetCharacterOrder(character, orderInfo.Order, orderInfo.OrderOption, priority, Character.Controlled);
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
OnSecondaryClicked = (button, userData) =>
|
OnSecondaryClicked = (button, userData) =>
|
||||||
@@ -1153,105 +1154,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Context Menu
|
|
||||||
|
|
||||||
public void CreateModerationContextMenu(Point mousePos, Client client)
|
|
||||||
{
|
|
||||||
if (GUIContextMenu.CurrentContextMenu != null) { return; }
|
|
||||||
if (IsSinglePlayer || client == null || ((!GameMain.Client?.PreviouslyConnectedClients?.Contains(client)) ?? true)) { return; }
|
|
||||||
|
|
||||||
|
|
||||||
bool hasSteam = client.SteamID > 0 && SteamManager.IsInitialized,
|
|
||||||
canKick = GameMain.Client.HasPermission(ClientPermissions.Kick),
|
|
||||||
canBan = GameMain.Client.HasPermission(ClientPermissions.Ban) && client.AllowKicking,
|
|
||||||
canPromo = GameMain.Client.HasPermission(ClientPermissions.ManagePermissions);
|
|
||||||
|
|
||||||
// Disable options if we are targeting ourselves
|
|
||||||
if (client.ID == GameMain.Client?.ID)
|
|
||||||
{
|
|
||||||
canKick = canBan = canPromo = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<ContextMenuOption> options = new List<ContextMenuOption>();
|
|
||||||
|
|
||||||
options.Add(new ContextMenuOption("ViewSteamProfile", isEnabled: hasSteam, onSelected: delegate
|
|
||||||
{
|
|
||||||
Steamworks.SteamFriends.OpenWebOverlay($"https://steamcommunity.com/profiles/{client.SteamID}");
|
|
||||||
}));
|
|
||||||
|
|
||||||
options.Add(new ContextMenuOption("ModerationMenu.UserDetails", isEnabled: true, onSelected: delegate
|
|
||||||
{
|
|
||||||
GameMain.NetLobbyScreen?.SelectPlayer(client);
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
// Creates sub context menu options for all the ranks
|
|
||||||
List<ContextMenuOption> permissionOptions = new List<ContextMenuOption>();
|
|
||||||
foreach (PermissionPreset rank in PermissionPreset.List)
|
|
||||||
{
|
|
||||||
permissionOptions.Add(new ContextMenuOption(rank.Name, isEnabled: true, onSelected: () =>
|
|
||||||
{
|
|
||||||
string label = TextManager.GetWithVariables(rank.Permissions == ClientPermissions.None ? "clearrankprompt" : "giverankprompt", new []{ "[user]", "[rank]" }, new []{ client.Name, rank.Name });
|
|
||||||
GUIMessageBox msgBox = new GUIMessageBox(string.Empty, label, new[] { TextManager.Get("Yes"), TextManager.Get("Cancel") });
|
|
||||||
|
|
||||||
msgBox.Buttons[0].OnClicked = delegate
|
|
||||||
{
|
|
||||||
client.SetPermissions(rank.Permissions, rank.PermittedCommands);
|
|
||||||
GameMain.Client.UpdateClientPermissions(client);
|
|
||||||
msgBox.Close();
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
msgBox.Buttons[1].OnClicked = delegate
|
|
||||||
{
|
|
||||||
msgBox.Close();
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
}) { Tooltip = rank.Description });
|
|
||||||
}
|
|
||||||
|
|
||||||
options.Add(new ContextMenuOption("Permissions", isEnabled: canPromo, options: permissionOptions.ToArray()));
|
|
||||||
|
|
||||||
Color clientColor = client.Character?.Info?.Job.Prefab.UIColor ?? Color.White;
|
|
||||||
|
|
||||||
if (GameMain.Client.ConnectedClients.Contains(client))
|
|
||||||
{
|
|
||||||
options.Add(new ContextMenuOption(client.MutedLocally ? "Unmute" : "Mute", isEnabled: client.ID != GameMain.Client?.ID, onSelected: delegate
|
|
||||||
{
|
|
||||||
client.MutedLocally = !client.MutedLocally;
|
|
||||||
}));
|
|
||||||
|
|
||||||
bool kickEnabled = client.ID != GameMain.Client?.ID && client.AllowKicking;
|
|
||||||
|
|
||||||
// if the user can kick create a kick option else create the votekick option
|
|
||||||
ContextMenuOption kickOption;
|
|
||||||
if (canKick)
|
|
||||||
{
|
|
||||||
kickOption = new ContextMenuOption("Kick", isEnabled: kickEnabled, onSelected: delegate
|
|
||||||
{
|
|
||||||
GameMain.Client?.CreateKickReasonPrompt(client.Name, false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
kickOption = new ContextMenuOption("VoteToKick", isEnabled: kickEnabled, onSelected: delegate
|
|
||||||
{
|
|
||||||
GameMain.Client?.VoteForKick(client);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
options.Add(kickOption);
|
|
||||||
}
|
|
||||||
|
|
||||||
options.Add(new ContextMenuOption("Ban", isEnabled: canBan, onSelected: delegate
|
|
||||||
{
|
|
||||||
GameMain.Client?.CreateKickReasonPrompt(client.Name, true);
|
|
||||||
}));
|
|
||||||
|
|
||||||
GUIContextMenu.CreateContextMenu(null, client.Name, headerColor: clientColor, options.ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public void AddToGUIUpdateList()
|
public void AddToGUIUpdateList()
|
||||||
{
|
{
|
||||||
if (GUI.DisableHUD) { return; }
|
if (GUI.DisableHUD) { return; }
|
||||||
@@ -1902,7 +1804,7 @@ namespace Barotrauma
|
|||||||
private Hull hullContext;
|
private Hull hullContext;
|
||||||
private WallSection wallContext;
|
private WallSection wallContext;
|
||||||
private bool isContextual;
|
private bool isContextual;
|
||||||
private readonly List<Order> contextualOrders = new List<Order>();
|
private readonly List<OrderInfo> contextualOrders = new List<OrderInfo>();
|
||||||
private Point shorcutCenterNodeOffset;
|
private Point shorcutCenterNodeOffset;
|
||||||
private const int maxShortcutNodeCount = 4;
|
private const int maxShortcutNodeCount = 4;
|
||||||
|
|
||||||
@@ -2605,7 +2507,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
order = orders[i];
|
order = orders[i];
|
||||||
disableNode = !CanCharacterBeHeard() ||
|
disableNode = !CanCharacterBeHeard() ||
|
||||||
(order.MustSetTarget && (order.ItemComponentType != null || order.TargetItems.Length > 0) &&
|
(order.MustSetTarget && (order.ItemComponentType != null || order.GetTargetItems().Any() || order.RequireItems.Any()) &&
|
||||||
order.GetMatchingItems(true, interactableFor: characterContext ?? Character.Controlled).None());
|
order.GetMatchingItems(true, interactableFor: characterContext ?? Character.Controlled).None());
|
||||||
optionNodes.Add(new Tuple<GUIComponent, Keys>(
|
optionNodes.Add(new Tuple<GUIComponent, Keys>(
|
||||||
CreateOrderNode(nodeSize, commandFrame.RectTransform, offsets[i].ToPoint(), order, (i + 1) % 10, disableNode: disableNode, checkIfOrderCanBeHeard: false),
|
CreateOrderNode(nodeSize, commandFrame.RectTransform, offsets[i].ToPoint(), order, (i + 1) % 10, disableNode: disableNode, checkIfOrderCanBeHeard: false),
|
||||||
@@ -2621,7 +2523,6 @@ namespace Barotrauma
|
|||||||
if (contextualOrders.None())
|
if (contextualOrders.None())
|
||||||
{
|
{
|
||||||
string orderIdentifier;
|
string orderIdentifier;
|
||||||
|
|
||||||
// Check if targeting an item or a hull
|
// Check if targeting an item or a hull
|
||||||
if (itemContext != null && itemContext.IsPlayerTeamInteractable)
|
if (itemContext != null && itemContext.IsPlayerTeamInteractable)
|
||||||
{
|
{
|
||||||
@@ -2630,84 +2531,89 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
targetComponent = null;
|
targetComponent = null;
|
||||||
if (p.UseController && itemContext.Components.None(c => c is Controller)) { continue; }
|
if (p.UseController && itemContext.Components.None(c => c is Controller)) { continue; }
|
||||||
if ((p.TargetItems.Length > 0 && (p.TargetItems.Contains(itemContext.Prefab.Identifier) || itemContext.HasTag(p.TargetItems))) ||
|
if (p.HasOptionSpecificTargetItems)
|
||||||
p.TryGetTargetItemComponent(itemContext, out targetComponent))
|
|
||||||
{
|
{
|
||||||
contextualOrders.Add(p.HasOptions ? p : new Order(p, itemContext, targetComponent, Character.Controlled));
|
foreach (string option in p.Options)
|
||||||
|
{
|
||||||
|
if (p.TargetItemsMatchItem(itemContext, option))
|
||||||
|
{
|
||||||
|
contextualOrders.Add(new OrderInfo(new Order(p, itemContext, targetComponent, Character.Controlled), option));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (p.TargetItemsMatchItem(itemContext) || p.TryGetTargetItemComponent(itemContext, out targetComponent))
|
||||||
|
{
|
||||||
|
contextualOrders.Add(new OrderInfo(p.HasOptions ? p : new Order(p, itemContext, targetComponent, Character.Controlled), null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If targeting a periscope connected to a turret, show the 'operateweapons' order
|
// If targeting a periscope connected to a turret, show the 'operateweapons' order
|
||||||
orderIdentifier = "operateweapons";
|
orderIdentifier = "operateweapons";
|
||||||
var operateWeaponsPrefab = Order.GetPrefab(orderIdentifier);
|
var operateWeaponsPrefab = Order.GetPrefab(orderIdentifier);
|
||||||
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)) && itemContext.Components.Any(c => c is Controller))
|
if (contextualOrders.None(info => info.Order.Identifier.Equals(orderIdentifier)) && itemContext.Components.Any(c => c is Controller))
|
||||||
{
|
{
|
||||||
var turret = itemContext.GetConnectedComponents<Turret>().FirstOrDefault(c => c.Item.HasTag(operateWeaponsPrefab.TargetItems)) ??
|
var turret = itemContext.GetConnectedComponents<Turret>().FirstOrDefault(c => operateWeaponsPrefab.TargetItemsMatchItem(c.Item)) ??
|
||||||
itemContext.GetConnectedComponents<Turret>(recursive: true).FirstOrDefault(c => c.Item.HasTag(operateWeaponsPrefab.TargetItems));
|
itemContext.GetConnectedComponents<Turret>(recursive: true).FirstOrDefault(c => operateWeaponsPrefab.TargetItemsMatchItem(c.Item));
|
||||||
if (turret != null) { contextualOrders.Add(new Order(operateWeaponsPrefab, turret.Item, turret, Character.Controlled)); }
|
if (turret != null)
|
||||||
|
{
|
||||||
|
contextualOrders.Add(new OrderInfo(new Order(operateWeaponsPrefab, turret.Item, turret, Character.Controlled), null));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If targeting a repairable item with condition below the repair threshold, show the 'repairsystems' order
|
// If targeting a repairable item with condition below the repair threshold, show the 'repairsystems' order
|
||||||
orderIdentifier = "repairsystems";
|
orderIdentifier = "repairsystems";
|
||||||
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)) && itemContext.Repairables.Any(r => r.IsBelowRepairThreshold))
|
if (contextualOrders.None(info => info.Order.Identifier.Equals(orderIdentifier)) && itemContext.Repairables.Any(r => r.IsBelowRepairThreshold))
|
||||||
{
|
{
|
||||||
if (itemContext.Repairables.Any(r => r != null && r.requiredSkills.Any(s => s != null && s.Identifier.Equals("electrical"))))
|
if (itemContext.Repairables.Any(r => r != null && r.requiredSkills.Any(s => s != null && s.Identifier.Equals("electrical"))))
|
||||||
{
|
{
|
||||||
contextualOrders.Add(new Order(Order.GetPrefab("repairelectrical"), itemContext, targetItem: null, Character.Controlled));
|
contextualOrders.Add(new OrderInfo(new Order(Order.GetPrefab("repairelectrical"), itemContext, targetItem: null, Character.Controlled), null));
|
||||||
}
|
}
|
||||||
else if (itemContext.Repairables.Any(r => r != null && r.requiredSkills.Any(s => s != null && s.Identifier.Equals("mechanical"))))
|
else if (itemContext.Repairables.Any(r => r != null && r.requiredSkills.Any(s => s != null && s.Identifier.Equals("mechanical"))))
|
||||||
{
|
{
|
||||||
contextualOrders.Add(new Order(Order.GetPrefab("repairmechanical"), itemContext, targetItem: null, Character.Controlled));
|
contextualOrders.Add(new OrderInfo(new Order(Order.GetPrefab("repairmechanical"), itemContext, targetItem: null, Character.Controlled), null));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), itemContext, targetItem: null, Character.Controlled));
|
contextualOrders.Add(new OrderInfo(new Order(Order.GetPrefab(orderIdentifier), itemContext, targetItem: null, Character.Controlled), null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the 'pumpwater' order if the target pump is auto-controlled (as it will immediately overwrite the work done by the bot)
|
// Remove the 'pumpwater' order if the target pump is auto-controlled (as it will immediately overwrite the work done by the bot)
|
||||||
orderIdentifier = "pumpwater";
|
orderIdentifier = "pumpwater";
|
||||||
if (contextualOrders.FirstOrDefault(o => o.Identifier.Equals(orderIdentifier)) is Order o &&
|
if (contextualOrders.FirstOrDefault(info => info.Order.Identifier.Equals(orderIdentifier)) is OrderInfo pumpOrderInfo && pumpOrderInfo.Order is Order pumpOrder &&
|
||||||
itemContext.Components.FirstOrDefault(c => c.GetType() == o.ItemComponentType) is Pump pump)
|
itemContext.Components.FirstOrDefault(c => c.GetType() == pumpOrder.ItemComponentType) is Pump pump && pump.IsAutoControlled)
|
||||||
{
|
{
|
||||||
if (pump.IsAutoControlled) { contextualOrders.Remove(o); }
|
contextualOrders.Remove(pumpOrderInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contextualOrders.None())
|
if (contextualOrders.None())
|
||||||
{
|
{
|
||||||
orderIdentifier = "cleanupitems";
|
orderIdentifier = "cleanupitems";
|
||||||
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)))
|
if (contextualOrders.None(info => info.Order.Identifier.Equals(orderIdentifier)))
|
||||||
{
|
{
|
||||||
if (AIObjectiveCleanupItems.IsValidTarget(itemContext, Character.Controlled, checkInventory: false) || AIObjectiveCleanupItems.IsValidContainer(itemContext, Character.Controlled))
|
if (AIObjectiveCleanupItems.IsValidTarget(itemContext, Character.Controlled, checkInventory: false) || AIObjectiveCleanupItems.IsValidContainer(itemContext, Character.Controlled))
|
||||||
{
|
{
|
||||||
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), itemContext, targetItem: null, Character.Controlled));
|
contextualOrders.Add(new OrderInfo(new Order(Order.GetPrefab(orderIdentifier), itemContext, targetItem: null, Character.Controlled), null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AddIgnoreOrder(itemContext);
|
AddIgnoreOrder(itemContext);
|
||||||
}
|
}
|
||||||
else if (hullContext != null)
|
else if (hullContext != null)
|
||||||
{
|
{
|
||||||
contextualOrders.Add(new Order(Order.GetPrefab("fixleaks"), hullContext, targetItem: null, Character.Controlled));
|
contextualOrders.Add(new OrderInfo(new Order(Order.GetPrefab("fixleaks"), hullContext, targetItem: null, Character.Controlled), null));
|
||||||
|
|
||||||
if (wallContext != null)
|
if (wallContext != null)
|
||||||
{
|
{
|
||||||
AddIgnoreOrder(wallContext);
|
AddIgnoreOrder(wallContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddIgnoreOrder(IIgnorable target)
|
void AddIgnoreOrder(IIgnorable target)
|
||||||
{
|
{
|
||||||
var orderIdentifier = "ignorethis";
|
var orderIdentifier = "ignorethis";
|
||||||
if (!target.OrderedToBeIgnored && contextualOrders.None(o => o.Identifier == orderIdentifier))
|
if (!target.OrderedToBeIgnored && contextualOrders.None(info => info.Order.Identifier == orderIdentifier))
|
||||||
{
|
{
|
||||||
AddOrder();
|
AddOrder();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
orderIdentifier = "unignorethis";
|
orderIdentifier = "unignorethis";
|
||||||
if (target.OrderedToBeIgnored && contextualOrders.None(o => o.Identifier == orderIdentifier))
|
if (target.OrderedToBeIgnored && contextualOrders.None(info => info.Order.Identifier == orderIdentifier))
|
||||||
{
|
{
|
||||||
AddOrder();
|
AddOrder();
|
||||||
}
|
}
|
||||||
@@ -2717,64 +2623,61 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (target is WallSection ws)
|
if (target is WallSection ws)
|
||||||
{
|
{
|
||||||
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), ws.Wall, ws.Wall.Sections.IndexOf(ws), orderGiver: Character.Controlled));
|
contextualOrders.Add(new OrderInfo(new Order(Order.GetPrefab(orderIdentifier), ws.Wall, ws.Wall.Sections.IndexOf(ws), orderGiver: Character.Controlled), null));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), target as Entity, null, Character.Controlled));
|
contextualOrders.Add(new OrderInfo(new Order(Order.GetPrefab(orderIdentifier), target as Entity, null, Character.Controlled), null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
orderIdentifier = "wait";
|
orderIdentifier = "wait";
|
||||||
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)))
|
if (contextualOrders.None(info => info.Order.Identifier.Equals(orderIdentifier)))
|
||||||
{
|
{
|
||||||
Vector2 position = GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
|
Vector2 position = GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||||
Hull hull = Hull.FindHull(position, guess: Character.Controlled?.CurrentHull);
|
Hull hull = Hull.FindHull(position, guess: Character.Controlled?.CurrentHull);
|
||||||
contextualOrders.Add(new Order(Order.GetPrefab(orderIdentifier), new OrderTarget(position, hull), Character.Controlled));
|
contextualOrders.Add(new OrderInfo(new Order(Order.GetPrefab(orderIdentifier), new OrderTarget(position, hull), Character.Controlled), null));
|
||||||
}
|
}
|
||||||
|
if (contextualOrders.None(info => info.Order.Category != OrderCategory.Movement) && characters.Any(c => c != Character.Controlled))
|
||||||
if (contextualOrders.None(o => o.Category != OrderCategory.Movement) && characters.Any(c => c != Character.Controlled))
|
|
||||||
{
|
{
|
||||||
orderIdentifier = "follow";
|
orderIdentifier = "follow";
|
||||||
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)))
|
if (contextualOrders.None(info => info.Order.Identifier.Equals(orderIdentifier)))
|
||||||
{
|
{
|
||||||
contextualOrders.Add(Order.GetPrefab(orderIdentifier));
|
contextualOrders.Add(new OrderInfo(Order.GetPrefab(orderIdentifier), null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show 'dismiss' order only when there are crew members with active orders
|
// Show 'dismiss' order only when there are crew members with active orders
|
||||||
orderIdentifier = "dismissed";
|
orderIdentifier = "dismissed";
|
||||||
if (contextualOrders.None(o => o.Identifier.Equals(orderIdentifier)) && characters.Any(c => !c.IsDismissed))
|
if (contextualOrders.None(info => info.Order.Identifier.Equals(orderIdentifier)) && characters.Any(c => !c.IsDismissed))
|
||||||
{
|
{
|
||||||
contextualOrders.Add(Order.GetPrefab(orderIdentifier));
|
contextualOrders.Add(new OrderInfo(Order.GetPrefab(orderIdentifier), null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, nodeDistance, contextualOrders.Count, MathHelper.ToRadians(90f + 180f / contextualOrders.Count));
|
var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, nodeDistance, contextualOrders.Count, MathHelper.ToRadians(90f + 180f / contextualOrders.Count));
|
||||||
bool disableNode = !CanCharacterBeHeard();
|
bool disableNode = !CanCharacterBeHeard();
|
||||||
for (int i = 0; i < contextualOrders.Count; i++)
|
for (int i = 0; i < contextualOrders.Count; i++)
|
||||||
{
|
{
|
||||||
optionNodes.Add(new Tuple<GUIComponent, Keys>(
|
var info = contextualOrders[i];
|
||||||
CreateOrderNode(nodeSize, commandFrame.RectTransform, offsets[i].ToPoint(), contextualOrders[i], (i + 1) % 10, disableNode: disableNode, checkIfOrderCanBeHeard: false),
|
int hotkey = (i + 1) % 10;
|
||||||
!disableNode ? Keys.D0 + (i + 1) % 10 : Keys.None));
|
var component = string.IsNullOrEmpty(info.OrderOption) ?
|
||||||
|
CreateOrderNode(nodeSize, commandFrame.RectTransform, offsets[i].ToPoint(), info.Order, hotkey, disableNode: disableNode, checkIfOrderCanBeHeard: false) :
|
||||||
|
CreateOrderOptionNode(nodeSize, commandFrame.RectTransform, offsets[i].ToPoint(), info.Order, info.OrderOption, info.Order.Prefab.GetOptionName(info.OrderOption), hotkey);
|
||||||
|
optionNodes.Add(new Tuple<GUIComponent, Keys>(component, !disableNode ? Keys.D0 + (i + 1) % 10 : Keys.None));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: there's duplicate logic here and above -> would be better to refactor so that the conditions are only defined in one place
|
// TODO: there's duplicate logic here and above -> would be better to refactor so that the conditions are only defined in one place
|
||||||
public static bool DoesItemHaveContextualOrders(Item item)
|
public static bool DoesItemHaveContextualOrders(Item item)
|
||||||
{
|
{
|
||||||
if (Order.PrefabList.Any(o => o.TargetItems.Length > 0 && o.TargetItems.Contains(item.Prefab.Identifier))) { return true; }
|
if (Order.PrefabList.Any(o => o.TargetItemsMatchItem(item))) { return true; }
|
||||||
if (Order.PrefabList.Any(o => item.HasTag(o.TargetItems))) { return true; }
|
|
||||||
if (Order.PrefabList.Any(o => o.TryGetTargetItemComponent(item, out _))) { return true; }
|
if (Order.PrefabList.Any(o => o.TryGetTargetItemComponent(item, out _))) { return true; }
|
||||||
if (AIObjectiveCleanupItems.IsValidTarget(item, Character.Controlled, checkInventory: false)) { return true; }
|
if (AIObjectiveCleanupItems.IsValidTarget(item, Character.Controlled, checkInventory: false)) { return true; }
|
||||||
if (AIObjectiveCleanupItems.IsValidContainer(item, Character.Controlled)) { return true; }
|
if (AIObjectiveCleanupItems.IsValidContainer(item, Character.Controlled)) { return true; }
|
||||||
|
if (Order.GetPrefab("loaditems") is Order loadItemsPrefab && AIObjectiveLoadItems.IsValidTarget(item, Character.Controlled, targetContainerTags: loadItemsPrefab.GetTargetItems())) { return true; }
|
||||||
if (item.Repairables.Any(r => r.IsBelowRepairThreshold)) { return true; }
|
if (item.Repairables.Any(r => r.IsBelowRepairThreshold)) { return true; }
|
||||||
var operateWeaponsPrefab = Order.GetPrefab("operateweapons");
|
return Order.GetPrefab("operateweapons") is Order operateWeaponsPrefab && item.Components.Any(c => c is Controller) &&
|
||||||
return item.Components.Any(c => c is Controller) &&
|
(item.GetConnectedComponents<Turret>().Any(c => operateWeaponsPrefab.TargetItemsMatchItem(c.Item)) ||
|
||||||
(item.GetConnectedComponents<Turret>().Any(c => c.Item.HasTag(operateWeaponsPrefab.TargetItems)) ||
|
item.GetConnectedComponents<Turret>(recursive: true).Any(c => operateWeaponsPrefab.TargetItemsMatchItem(c.Item)));
|
||||||
item.GetConnectedComponents<Turret>(recursive: true).Any(c => c.Item.HasTag(operateWeaponsPrefab.TargetItems)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <param name="hotkey">Use a negative value (e.g. -1) if there should be no hotkey associated with the node</param>
|
/// <param name="hotkey">Use a negative value (e.g. -1) if there should be no hotkey associated with the node</param>
|
||||||
@@ -2831,7 +2734,8 @@ namespace Barotrauma
|
|||||||
o = new Order(o.Prefab, orderTargetEntity, orderTargetEntity.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType), orderGiver: order.OrderGiver);
|
o = new Order(o.Prefab, orderTargetEntity, orderTargetEntity.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType), orderGiver: order.OrderGiver);
|
||||||
}
|
}
|
||||||
var character = !o.TargetAllCharacters ? characterContext ?? GetCharacterForQuickAssignment(o) : null;
|
var character = !o.TargetAllCharacters ? characterContext ?? GetCharacterForQuickAssignment(o) : null;
|
||||||
SetCharacterOrder(character, o, null, CharacterInfo.HighestManualOrderPriority, Character.Controlled);
|
int priority = GetManualOrderPriority(character, o);
|
||||||
|
SetCharacterOrder(character, o, null, priority, Character.Controlled);
|
||||||
DisableCommandUI();
|
DisableCommandUI();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -2943,7 +2847,9 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SetCharacterOrder(characterContext ?? GetCharacterForQuickAssignment(o.Item1), o.Item1, o.Item2, CharacterInfo.HighestManualOrderPriority, Character.Controlled);
|
var character = characterContext ?? GetCharacterForQuickAssignment(o.Item1);
|
||||||
|
int priority = GetManualOrderPriority(character, o.Item1);
|
||||||
|
SetCharacterOrder(character, o.Item1, o.Item2, priority, Character.Controlled);
|
||||||
DisableCommandUI();
|
DisableCommandUI();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -3013,7 +2919,9 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SetCharacterOrder(characterContext ?? GetCharacterForQuickAssignment(o.Item1), o.Item1, o.Item2, CharacterInfo.HighestManualOrderPriority, Character.Controlled);
|
var character = characterContext ?? GetCharacterForQuickAssignment(o.Item1);
|
||||||
|
int priority = GetManualOrderPriority(character, o.Item1);
|
||||||
|
SetCharacterOrder(character, o.Item1, o.Item2, priority, Character.Controlled);
|
||||||
DisableCommandUI();
|
DisableCommandUI();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -3218,7 +3126,9 @@ namespace Barotrauma
|
|||||||
OnClicked = (_, userData) =>
|
OnClicked = (_, userData) =>
|
||||||
{
|
{
|
||||||
if (!CanIssueOrders) { return false; }
|
if (!CanIssueOrders) { return false; }
|
||||||
SetCharacterOrder(userData as Character, order.Item1, order.Item2, CharacterInfo.HighestManualOrderPriority, Character.Controlled);
|
var character = userData as Character;
|
||||||
|
int priority = GetManualOrderPriority(character, order.Item1);
|
||||||
|
SetCharacterOrder(character, order.Item1, order.Item2, priority, Character.Controlled);
|
||||||
DisableCommandUI();
|
DisableCommandUI();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -3496,6 +3406,11 @@ namespace Barotrauma
|
|||||||
return order.Name;
|
return order.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int GetManualOrderPriority(Character character, Order order)
|
||||||
|
{
|
||||||
|
return character?.Info?.GetManualOrderPriority(order) ?? CharacterInfo.HighestManualOrderPriority;
|
||||||
|
}
|
||||||
|
|
||||||
#region Crew Member Assignment Logic
|
#region Crew Member Assignment Logic
|
||||||
private bool CanOpenManualAssignment(GUIComponent node)
|
private bool CanOpenManualAssignment(GUIComponent node)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public override void ShowStartMessage()
|
public override void ShowStartMessage()
|
||||||
{
|
{
|
||||||
foreach (Mission mission in Missions)
|
foreach (Mission mission in Missions.ToList())
|
||||||
{
|
{
|
||||||
new GUIMessageBox(
|
new GUIMessageBox(
|
||||||
mission.Prefab.IsSideObjective ? TextManager.AddPunctuation(':', TextManager.Get("sideobjective"), mission.Name) : mission.Name,
|
mission.Prefab.IsSideObjective ? TextManager.AddPunctuation(':', TextManager.Get("sideobjective"), mission.Name) : mission.Name,
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ namespace Barotrauma
|
|||||||
var newCampaignContainer = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.95f), campaignContainer.RectTransform, Anchor.Center), style: null);
|
var newCampaignContainer = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.95f), campaignContainer.RectTransform, Anchor.Center), style: null);
|
||||||
var loadCampaignContainer = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.95f), campaignContainer.RectTransform, Anchor.Center), style: null);
|
var loadCampaignContainer = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.95f), campaignContainer.RectTransform, Anchor.Center), style: null);
|
||||||
|
|
||||||
GameMain.NetLobbyScreen.CampaignSetupUI = new MultiPlayerCampaignSetupUI(newCampaignContainer, loadCampaignContainer, null, saveFiles);
|
GameMain.NetLobbyScreen.CampaignSetupUI = new MultiPlayerCampaignSetupUI(newCampaignContainer, loadCampaignContainer, saveFiles);
|
||||||
|
|
||||||
var newCampaignButton = new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), buttonContainer.RectTransform),
|
var newCampaignButton = new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), buttonContainer.RectTransform),
|
||||||
TextManager.Get("NewCampaign"), style: "GUITabButton")
|
TextManager.Get("NewCampaign"), style: "GUITabButton")
|
||||||
|
|||||||
@@ -475,12 +475,12 @@ namespace Barotrauma
|
|||||||
ItemComponent targetItem = null;
|
ItemComponent targetItem = null;
|
||||||
if (orderPrefab.MustSetTarget)
|
if (orderPrefab.MustSetTarget)
|
||||||
{
|
{
|
||||||
targetEntity = orderPrefab.GetMatchingItems(true, interactableFor: Character.Controlled).FirstOrDefault();
|
targetEntity = orderPrefab.GetMatchingItems(true, interactableFor: Character.Controlled, orderOption: orderInfo.option).FirstOrDefault();
|
||||||
if (targetEntity == null) { return; }
|
if (targetEntity == null) { return; }
|
||||||
targetItem = orderPrefab.GetTargetItemComponent(targetEntity);
|
targetItem = orderPrefab.GetTargetItemComponent(targetEntity);
|
||||||
}
|
}
|
||||||
var order = new Order(orderPrefab, targetEntity as Entity, targetItem, orderGiver: Character.Controlled);
|
var order = new Order(orderPrefab, targetEntity as Entity, targetItem, orderGiver: Character.Controlled);
|
||||||
GameMain.GameSession.CrewManager.SetCharacterOrder(Character.Controlled, order, orderInfo.option, CharacterInfo.HighestManualOrderPriority, Character.Controlled);
|
GameMain.GameSession?.CrewManager?.SetCharacterOrder(Character.Controlled, order, orderInfo.option, CharacterInfo.HighestManualOrderPriority, Character.Controlled);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -635,9 +635,9 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else if (characterInfo.CauseOfDeath.Type == CauseOfDeathType.Affliction && characterInfo.CauseOfDeath.Affliction == null)
|
else if (characterInfo.CauseOfDeath.Type == CauseOfDeathType.Affliction && characterInfo.CauseOfDeath.Affliction == null)
|
||||||
{
|
{
|
||||||
string errorMsg = "Character \"" + characterInfo.Name + "\" had an invalid cause of death (the type of the cause of death was Affliction, but affliction was not specified).";
|
string errorMsg = "Character \"[name]\" had an invalid cause of death (the type of the cause of death was Affliction, but affliction was not specified).";
|
||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg.Replace("[name]", characterInfo.Name));
|
||||||
GameAnalyticsManager.AddErrorEventOnce("RoundSummary:InvalidCauseOfDeath", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("RoundSummary:InvalidCauseOfDeath", GameAnalyticsManager.ErrorSeverity.Error, errorMsg.Replace("[name]", characterInfo.SpeciesName));
|
||||||
statusText = TextManager.Get("CauseOfDeathDescription.Unknown");
|
statusText = TextManager.Get("CauseOfDeathDescription.Unknown");
|
||||||
statusColor = GUI.Style.Red;
|
statusColor = GUI.Style.Red;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
using Barotrauma.Extensions;
|
using Barotrauma.Networking;
|
||||||
using Barotrauma.Networking;
|
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using Microsoft.Xna.Framework.Input;
|
using Microsoft.Xna.Framework.Input;
|
||||||
using OpenAL;
|
using OpenAL;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
|
||||||
@@ -365,6 +363,12 @@ namespace Barotrauma
|
|||||||
TextManager.Get("Settings"), textAlignment: Alignment.TopLeft, font: GUI.LargeFont)
|
TextManager.Get("Settings"), textAlignment: Alignment.TopLeft, font: GUI.LargeFont)
|
||||||
{ ForceUpperCase = true };
|
{ ForceUpperCase = true };
|
||||||
|
|
||||||
|
new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), settingsTitle.RectTransform, Anchor.CenterRight, scaleBasis: ScaleBasis.Smallest), style: "GUIBugButton")
|
||||||
|
{
|
||||||
|
ToolTip = TextManager.Get("bugreportbutton") + $" (v{GameMain.Version})",
|
||||||
|
OnClicked = (btn, userdata) => { GameMain.Instance.ShowBugReporter(); return true; }
|
||||||
|
};
|
||||||
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftPanel.RectTransform), TextManager.Get("ContentPackages"), font: GUI.SubHeadingFont);
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftPanel.RectTransform), TextManager.Get("ContentPackages"), font: GUI.SubHeadingFont);
|
||||||
|
|
||||||
var corePackageDropdown = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), leftPanel.RectTransform))
|
var corePackageDropdown = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), leftPanel.RectTransform))
|
||||||
@@ -509,17 +513,53 @@ namespace Barotrauma
|
|||||||
ApplySettings();
|
ApplySettings();
|
||||||
GameMain.Instance.Exit();
|
GameMain.Instance.Exit();
|
||||||
return true;
|
return true;
|
||||||
}; msgBox.Buttons[1].OnClicked += (btn, userdata) =>
|
};
|
||||||
|
msgBox.Buttons[1].OnClicked += (btn, userdata) =>
|
||||||
{
|
{
|
||||||
Language = prevLanguage;
|
Language = prevLanguage;
|
||||||
languageDD.SelectItem(Language);
|
languageDD.SelectItem(Language);
|
||||||
msgBox.Close();
|
msgBox.Close();
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var statisticsTickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.045f), leftPanel.RectTransform), TextManager.Get("statisticsconsenttickbox"))
|
||||||
|
{
|
||||||
|
OnSelected = (GUITickBox tickBox) =>
|
||||||
|
{
|
||||||
|
GameAnalyticsManager.SetConsent(
|
||||||
|
tickBox.Selected
|
||||||
|
? GameAnalyticsManager.Consent.Ask
|
||||||
|
: GameAnalyticsManager.Consent.No);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
void updateGATickBoxToolTip()
|
||||||
|
=> statisticsTickBox.ToolTip = TextManager.Get($"GameAnalyticsStatus.{GameAnalyticsManager.UserConsented}");
|
||||||
|
updateGATickBoxToolTip();
|
||||||
|
|
||||||
|
var cachedConsent = GameAnalyticsManager.Consent.Unknown;
|
||||||
|
var statisticsTickBoxUpdater = new GUICustomComponent(
|
||||||
|
new RectTransform(Vector2.Zero, statisticsTickBox.RectTransform),
|
||||||
|
onUpdate: (deltaTime, component) =>
|
||||||
|
{
|
||||||
|
bool shouldTickBoxBeSelected = GameAnalyticsManager.UserConsented == GameAnalyticsManager.Consent.Yes;
|
||||||
|
|
||||||
|
bool shouldUpdateTickBoxState = cachedConsent != GameAnalyticsManager.UserConsented
|
||||||
|
|| statisticsTickBox.Selected != shouldTickBoxBeSelected;
|
||||||
|
|
||||||
|
if (!shouldUpdateTickBoxState) { return; }
|
||||||
|
|
||||||
|
updateGATickBoxToolTip();
|
||||||
|
cachedConsent = GameAnalyticsManager.UserConsented;
|
||||||
|
GUITickBox.OnSelectedHandler prevHandler = statisticsTickBox.OnSelected;
|
||||||
|
statisticsTickBox.OnSelected = null;
|
||||||
|
statisticsTickBox.Selected = shouldTickBoxBeSelected;
|
||||||
|
statisticsTickBox.OnSelected = prevHandler;
|
||||||
|
statisticsTickBox.Enabled = GameAnalyticsManager.UserConsented != GameAnalyticsManager.Consent.Error;
|
||||||
|
});
|
||||||
|
|
||||||
// right panel --------------------------------------
|
// right panel --------------------------------------
|
||||||
|
|
||||||
var rightPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.99f - leftPanel.RectTransform.RelativeSize.X, leftPanel.RectTransform.RelativeSize.Y),
|
var rightPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.99f - leftPanel.RectTransform.RelativeSize.X, leftPanel.RectTransform.RelativeSize.Y),
|
||||||
@@ -556,13 +596,6 @@ namespace Barotrauma
|
|||||||
tabButtons[(int)tab].Text = ToolBox.LimitString(buttonText, tabButtons[(int)tab].Font, (int)(0.75f * tabWidth * tabButtonHolder.Rect.Width));
|
tabButtons[(int)tab].Text = ToolBox.LimitString(buttonText, tabButtons[(int)tab].Font, (int)(0.75f * tabWidth * tabButtonHolder.Rect.Width));
|
||||||
}
|
}
|
||||||
|
|
||||||
new GUIButton(new RectTransform(new Vector2(0.05f, 0.75f), tabButtonHolder.RectTransform, Anchor.BottomRight) { RelativeOffset = new Vector2(0.0f, 0.2f) }, style: "GUIBugButton")
|
|
||||||
{
|
|
||||||
ToolTip = TextManager.Get("bugreportbutton"),
|
|
||||||
OnClicked = (btn, userdata) => { GameMain.Instance.ShowBugReporter(); return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/// Graphics tab --------------------------------------------------------------
|
/// Graphics tab --------------------------------------------------------------
|
||||||
|
|
||||||
var leftColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.46f, 0.95f), tabs[(int)Tab.Graphics].RectTransform, Anchor.TopLeft)
|
var leftColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.46f, 0.95f), tabs[(int)Tab.Graphics].RectTransform, Anchor.TopLeft)
|
||||||
@@ -1168,7 +1201,7 @@ namespace Barotrauma
|
|||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Failed to set voice capture mode.", e);
|
DebugConsole.ThrowError("Failed to set voice capture mode.", e);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("SetVoiceCaptureMode", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, "Failed to set voice capture mode. " + e.Message + "\n" + e.StackTrace.CleanupStackTrace());
|
GameAnalyticsManager.AddErrorEventOnce("SetVoiceCaptureMode", GameAnalyticsManager.ErrorSeverity.Error, "Failed to set voice capture mode. " + e.Message + "\n" + e.StackTrace.CleanupStackTrace());
|
||||||
VoiceSetting = VoiceMode.Disabled;
|
VoiceSetting = VoiceMode.Disabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -406,7 +406,7 @@ namespace Barotrauma.Items.Components
|
|||||||
DebugConsole.Log("Invalid sound volume (item " + item.Name + ", " + GetType().ToString() + "): " + newVolume);
|
DebugConsole.Log("Invalid sound volume (item " + item.Name + ", " + GetType().ToString() + "): " + newVolume);
|
||||||
GameAnalyticsManager.AddErrorEventOnce(
|
GameAnalyticsManager.AddErrorEventOnce(
|
||||||
"ItemComponent.PlaySound:" + item.Name + GetType().ToString(),
|
"ItemComponent.PlaySound:" + item.Name + GetType().ToString(),
|
||||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
GameAnalyticsManager.ErrorSeverity.Error,
|
||||||
"Invalid sound volume (item " + item.Name + ", " + GetType().ToString() + "): " + newVolume);
|
"Invalid sound volume (item " + item.Name + ", " + GetType().ToString() + "): " + newVolume);
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
using System;
|
using Microsoft.Xna.Framework;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using System.Xml.Linq;
|
|
||||||
using Microsoft.Xna.Framework;
|
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
|
||||||
namespace Barotrauma.Items.Components
|
namespace Barotrauma.Items.Components
|
||||||
{
|
{
|
||||||
@@ -11,7 +8,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
public float BackgroundSpriteDepth
|
public float BackgroundSpriteDepth
|
||||||
{
|
{
|
||||||
get { return item.GetDrawDepth() + 0.1f; }
|
get { return item.GetDrawDepth() + 0.05f; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector2 DrawSize
|
public Vector2 DrawSize
|
||||||
|
|||||||
@@ -672,36 +672,33 @@ namespace Barotrauma.Items.Components
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentMode == MiniMapMode.HullStatus)
|
if (currentMode == MiniMapMode.HullStatus && item.Submarine != null)
|
||||||
{
|
{
|
||||||
Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle;
|
Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle;
|
||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
|
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
|
||||||
spriteBatch.GraphicsDevice.ScissorRectangle = submarineContainer.Rect;
|
spriteBatch.GraphicsDevice.ScissorRectangle = submarineContainer.Rect;
|
||||||
|
|
||||||
if (item.Submarine != null)
|
var sprite = GUI.Style.UIGlowSolidCircular?.Sprite;
|
||||||
|
float alpha = (MathF.Sin(blipState / maxBlipState * MathHelper.TwoPi) + 1.5f) * 0.5f;
|
||||||
|
if (sprite != null)
|
||||||
{
|
{
|
||||||
var sprite = GUI.Style.UIGlowSolidCircular?.Sprite;
|
Vector2 spriteSize = sprite.size;
|
||||||
float alpha = (MathF.Sin(blipState / maxBlipState * MathHelper.TwoPi) + 1.5f) * 0.5f;
|
Rectangle worldBorders = item.Submarine.GetDockedBorders();
|
||||||
if (sprite != null)
|
worldBorders.Location += item.Submarine.WorldPosition.ToPoint();
|
||||||
|
foreach (Gap gap in Gap.GapList)
|
||||||
{
|
{
|
||||||
Vector2 spriteSize = sprite.size;
|
if (gap.IsRoomToRoom || gap.linkedTo.Count == 0 || gap.Submarine != item.Submarine || gap.ConnectedDoor != null || gap.HiddenInGame) { continue; }
|
||||||
Rectangle worldBorders = item.Submarine.GetDockedBorders();
|
RectangleF entityRect = ScaleRectToUI(gap, miniMapFrame.Rect, worldBorders);
|
||||||
worldBorders.Location += item.Submarine.WorldPosition.ToPoint();
|
|
||||||
foreach (Gap gap in Gap.GapList)
|
|
||||||
{
|
|
||||||
if (gap.IsRoomToRoom || gap.Submarine != item.Submarine || gap.ConnectedDoor != null || gap.HiddenInGame) { continue; }
|
|
||||||
RectangleF entityRect = ScaleRectToUI(gap, miniMapFrame.Rect, worldBorders);
|
|
||||||
|
|
||||||
Vector2 scale = new Vector2(entityRect.Size.X / spriteSize.X, entityRect.Size.Y / spriteSize.Y) * 2.0f;
|
Vector2 scale = new Vector2(entityRect.Size.X / spriteSize.X, entityRect.Size.Y / spriteSize.Y) * 2.0f;
|
||||||
|
|
||||||
Color color = ToolBox.GradientLerp(gap.Open, GUI.Style.HealthBarColorMedium, GUI.Style.HealthBarColorLow) * alpha;
|
Color color = ToolBox.GradientLerp(gap.Open, GUI.Style.HealthBarColorMedium, GUI.Style.HealthBarColorLow) * alpha;
|
||||||
sprite.Draw(spriteBatch,
|
sprite.Draw(spriteBatch,
|
||||||
miniMapFrame.Rect.Location.ToVector2() + entityRect.Center,
|
miniMapFrame.Rect.Location.ToVector2() + entityRect.Center,
|
||||||
color, origin: sprite.Origin, rotate: 0.0f, scale: scale);
|
color, origin: sprite.Origin, rotate: 0.0f, scale: scale);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentMode == MiniMapMode.HullStatus && hullStatusComponents != null)
|
if (currentMode == MiniMapMode.HullStatus && hullStatusComponents != null)
|
||||||
{
|
{
|
||||||
@@ -991,8 +988,40 @@ namespace Barotrauma.Items.Components
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
hullData.HullOxygenAmount = RequireOxygenDetectors ? hullData.ReceivedOxygenAmount : hull.OxygenPercentage;
|
if (RequireOxygenDetectors)
|
||||||
hullData.HullWaterAmount = RequireWaterDetectors ? hullData.ReceivedWaterAmount : Math.Min(hull.WaterVolume / hull.Volume, 1.0f);
|
{
|
||||||
|
hullData.HullOxygenAmount = hullData.ReceivedOxygenAmount;
|
||||||
|
}
|
||||||
|
else if (hullData.LinkedHulls.Any())
|
||||||
|
{
|
||||||
|
hullData.HullOxygenAmount = 0.0f;
|
||||||
|
foreach (Hull linkedHull in hullData.LinkedHulls)
|
||||||
|
{
|
||||||
|
hullData.HullOxygenAmount += linkedHull.OxygenPercentage;
|
||||||
|
}
|
||||||
|
hullData.HullOxygenAmount /= hullData.LinkedHulls.Count;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hullData.HullOxygenAmount = hull.OxygenPercentage;
|
||||||
|
}
|
||||||
|
if (RequireWaterDetectors)
|
||||||
|
{
|
||||||
|
hullData.HullWaterAmount = hullData.ReceivedWaterAmount;
|
||||||
|
}
|
||||||
|
else if (hullData.LinkedHulls.Any())
|
||||||
|
{
|
||||||
|
hullData.HullWaterAmount = 0.0f;
|
||||||
|
foreach (Hull linkedHull in hullData.LinkedHulls)
|
||||||
|
{
|
||||||
|
hullData.HullWaterAmount += Math.Min(linkedHull.WaterVolume / linkedHull.Volume, 1.0f);
|
||||||
|
}
|
||||||
|
hullData.HullWaterAmount /= hullData.LinkedHulls.Count;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hullData.HullWaterAmount = Math.Min(hull.WaterVolume / hull.Volume, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
float gapOpenSum = 0.0f;
|
float gapOpenSum = 0.0f;
|
||||||
|
|
||||||
@@ -1013,15 +1042,6 @@ namespace Barotrauma.Items.Components
|
|||||||
float? oxygenAmount = hullData.HullOxygenAmount,
|
float? oxygenAmount = hullData.HullOxygenAmount,
|
||||||
waterAmount = hullData.HullWaterAmount;
|
waterAmount = hullData.HullWaterAmount;
|
||||||
|
|
||||||
foreach (Hull linkedHull in hullData.LinkedHulls)
|
|
||||||
{
|
|
||||||
oxygenAmount += linkedHull.OxygenPercentage;
|
|
||||||
waterAmount += Math.Min(linkedHull.WaterVolume / linkedHull.Volume, 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
oxygenAmount /= (hullData.LinkedHulls.Count + 1);
|
|
||||||
waterAmount /= (hullData.LinkedHulls.Count + 1);
|
|
||||||
|
|
||||||
string line1 = gapOpenSum > 0.1f ? TextManager.Get("MiniMapHullBreach") : string.Empty;
|
string line1 = gapOpenSum > 0.1f ? TextManager.Get("MiniMapHullBreach") : string.Empty;
|
||||||
Color line1Color = GUI.Style.Red;
|
Color line1Color = GUI.Style.Red;
|
||||||
|
|
||||||
@@ -1111,10 +1131,9 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private void DrawHUDBack(SpriteBatch spriteBatch, GUICustomComponent container)
|
private void DrawHUDBack(SpriteBatch spriteBatch, GUICustomComponent container)
|
||||||
{
|
{
|
||||||
if (item.Submarine != null)
|
if (item.Submarine == null) { return; }
|
||||||
{
|
|
||||||
DrawSubmarine(spriteBatch);
|
DrawSubmarine(spriteBatch);
|
||||||
}
|
|
||||||
|
|
||||||
if (Voltage < MinVoltage) { return; }
|
if (Voltage < MinVoltage) { return; }
|
||||||
Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle;
|
Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle;
|
||||||
@@ -1155,7 +1174,8 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (hullsVisible && hullData.HullWaterAmount is { } waterAmount)
|
if (hullsVisible && hullData.HullWaterAmount is { } waterAmount)
|
||||||
{
|
{
|
||||||
if (hullFrame.Rect.Height * waterAmount > 3.0f)
|
if (!RequireWaterDetectors) { waterAmount = hull.WaterPercentage / 100.0f; }
|
||||||
|
if (hullFrame.Rect.Height * waterAmount > 1.0f)
|
||||||
{
|
{
|
||||||
RectangleF waterRect = new RectangleF(hullFrame.Rect.X, hullFrame.Rect.Y + hullFrame.Rect.Height * (1.0f - waterAmount), hullFrame.Rect.Width, hullFrame.Rect.Height * waterAmount);
|
RectangleF waterRect = new RectangleF(hullFrame.Rect.X, hullFrame.Rect.Y + hullFrame.Rect.Height * (1.0f - waterAmount), hullFrame.Rect.Width, hullFrame.Rect.Height * waterAmount);
|
||||||
|
|
||||||
@@ -1418,7 +1438,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
if (linkedEntity is Hull linkedHull)
|
if (linkedEntity is Hull linkedHull)
|
||||||
{
|
{
|
||||||
if (linkedHulls.Contains(linkedHull)) { continue; }
|
if (linkedHulls.Contains(linkedHull) || linkedHull.HiddenInGame) { continue; }
|
||||||
linkedHulls.Add(linkedHull);
|
linkedHulls.Add(linkedHull);
|
||||||
GetLinkedHulls(linkedHull, linkedHulls);
|
GetLinkedHulls(linkedHull, linkedHulls);
|
||||||
}
|
}
|
||||||
@@ -1598,7 +1618,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
bool IsPartofSub(MapEntity entity)
|
bool IsPartofSub(MapEntity entity)
|
||||||
{
|
{
|
||||||
if (entity.Submarine != sub && !connectedSubs.Contains(entity.Submarine)) { return false; }
|
if (entity.Submarine != sub && !connectedSubs.Contains(entity.Submarine) || entity.HiddenInGame) { return false; }
|
||||||
return !settings.IgnoreOutposts || sub.IsEntityFoundOnThisSub(entity, true);
|
return !settings.IgnoreOutposts || sub.IsEntityFoundOnThisSub(entity, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1623,6 +1623,11 @@ namespace Barotrauma.Items.Components
|
|||||||
markerDistances.Add(targetIdentifier, cachedDistance);
|
markerDistances.Add(targetIdentifier, cachedDistance);
|
||||||
dist = path.TotalLength;
|
dist = path.TotalLength;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var cachedDistance = new CachedDistance(transducerPosition, worldPosition, linearDist, Timing.TotalTime + Rand.Range(4.0f, 7.0f));
|
||||||
|
markerDistances.Add(targetIdentifier, cachedDistance);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2 position = worldPosition - transducerPosition;
|
Vector2 position = worldPosition - transducerPosition;
|
||||||
|
|||||||
@@ -35,6 +35,13 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private FixActions requestStartFixAction;
|
private FixActions requestStartFixAction;
|
||||||
|
|
||||||
|
private bool qteSuccess;
|
||||||
|
|
||||||
|
private float qteTimer;
|
||||||
|
private const float qteTime = 0.5f;
|
||||||
|
private float qteCooldown;
|
||||||
|
private const float qteCooldownTime = 0.5f;
|
||||||
|
|
||||||
public float FakeBrokenTimer;
|
public float FakeBrokenTimer;
|
||||||
|
|
||||||
[Serialize("", false, description: "An optional description of the needed repairs displayed in the repair interface.")]
|
[Serialize("", false, description: "An optional description of the needed repairs displayed in the repair interface.")]
|
||||||
@@ -55,16 +62,13 @@ namespace Barotrauma.Items.Components
|
|||||||
if (!HasRequiredItems(character, false) || character.SelectedConstruction != item) { return false; }
|
if (!HasRequiredItems(character, false) || character.SelectedConstruction != item) { return false; }
|
||||||
if (character.IsTraitor && item.ConditionPercentage > MinSabotageCondition) { return true; }
|
if (character.IsTraitor && item.ConditionPercentage > MinSabotageCondition) { return true; }
|
||||||
|
|
||||||
float maxRepairConditionMultiplier = GetMaxRepairConditionMultiplier(character);
|
float defaultMaxCondition = item.MaxCondition / item.MaxRepairConditionMultiplier;
|
||||||
float defaultMaxCondition = item.MaxCondition / maxRepairConditionMultiplier;
|
|
||||||
|
|
||||||
if (MathUtils.Percentage(item.Condition, defaultMaxCondition) < RepairThreshold) { return true; }
|
if (MathUtils.Percentage(item.Condition, defaultMaxCondition) < RepairThreshold) { return true; }
|
||||||
|
|
||||||
if (CurrentFixer == character)
|
if (CurrentFixer == character)
|
||||||
{
|
{
|
||||||
float condition = item.Condition / item.MaxRepairConditionMultiplier;
|
if (item.Condition < item.MaxCondition)
|
||||||
float maxCondition = item.MaxCondition / item.MaxRepairConditionMultiplier;
|
|
||||||
if (condition < maxCondition * maxRepairConditionMultiplier)
|
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -145,11 +149,14 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
progressBar = new GUIProgressBar(new RectTransform(new Vector2(0.6f, 1.0f), progressBarHolder.RectTransform),
|
progressBar = new GUIProgressBar(new RectTransform(new Vector2(0.6f, 1.0f), progressBarHolder.RectTransform),
|
||||||
color: GUI.Style.Green, barSize: 0.0f, style: "DeviceProgressBar");
|
color: GUI.Style.Green, barSize: 0.0f, style: "DeviceProgressBar");
|
||||||
|
|
||||||
progressBarOverlayText = new GUITextBlock(new RectTransform(Vector2.One, progressBar.RectTransform), string.Empty, font: GUI.SubHeadingFont, textAlignment: Alignment.Center)
|
progressBarOverlayText = new GUITextBlock(new RectTransform(Vector2.One, progressBar.RectTransform), string.Empty, font: GUI.SubHeadingFont, textAlignment: Alignment.Center)
|
||||||
{
|
{
|
||||||
IgnoreLayoutGroups = true
|
IgnoreLayoutGroups = true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
qteTimer = qteTime;
|
||||||
|
|
||||||
repairButtonText = TextManager.Get("RepairButton");
|
repairButtonText = TextManager.Get("RepairButton");
|
||||||
repairingText = TextManager.Get("Repairing");
|
repairingText = TextManager.Get("Repairing");
|
||||||
RepairButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1.0f), progressBarHolder.RectTransform, Anchor.TopCenter), repairButtonText)
|
RepairButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1.0f), progressBarHolder.RectTransform, Anchor.TopCenter), repairButtonText)
|
||||||
@@ -159,6 +166,11 @@ namespace Barotrauma.Items.Components
|
|||||||
requestStartFixAction = FixActions.Repair;
|
requestStartFixAction = FixActions.Repair;
|
||||||
item.CreateClientEvent(this);
|
item.CreateClientEvent(this);
|
||||||
return true;
|
return true;
|
||||||
|
},
|
||||||
|
OnButtonDown = () =>
|
||||||
|
{
|
||||||
|
QTEAction();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
RepairButton.TextBlock.AutoScaleHorizontal = true;
|
RepairButton.TextBlock.AutoScaleHorizontal = true;
|
||||||
@@ -183,6 +195,11 @@ namespace Barotrauma.Items.Components
|
|||||||
requestStartFixAction = FixActions.Sabotage;
|
requestStartFixAction = FixActions.Sabotage;
|
||||||
item.CreateClientEvent(this);
|
item.CreateClientEvent(this);
|
||||||
return true;
|
return true;
|
||||||
|
},
|
||||||
|
OnButtonDown = () =>
|
||||||
|
{
|
||||||
|
QTEAction();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -253,6 +270,21 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
repairSoundChannel = SoundPlayer.PlaySound("repair", item.WorldPosition, hullGuess: item.CurrentHull);
|
repairSoundChannel = SoundPlayer.PlaySound("repair", item.WorldPosition, hullGuess: item.CurrentHull);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (qteCooldown > 0.0f)
|
||||||
|
{
|
||||||
|
qteCooldown -= deltaTime;
|
||||||
|
if (qteCooldown <= 0.0f)
|
||||||
|
{
|
||||||
|
qteTimer = qteTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qteTimer -= deltaTime * (qteTimer / qteTime);
|
||||||
|
if (qteTimer < 0.0f) qteTimer = qteTime;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -270,6 +302,26 @@ namespace Barotrauma.Items.Components
|
|||||||
progressBar.BarSize = item.Condition / defaultMaxCondition;
|
progressBar.BarSize = item.Condition / defaultMaxCondition;
|
||||||
progressBar.Color = ToolBox.GradientLerp(progressBar.BarSize, GUI.Style.Red, GUI.Style.Orange, GUI.Style.Green);
|
progressBar.Color = ToolBox.GradientLerp(progressBar.BarSize, GUI.Style.Red, GUI.Style.Orange, GUI.Style.Green);
|
||||||
|
|
||||||
|
Rectangle sliderRect = progressBar.GetSliderRect(1.0f);
|
||||||
|
Color qteSliderColor = Color.White;
|
||||||
|
if (qteCooldown > 0.0f)
|
||||||
|
{
|
||||||
|
qteSliderColor = qteSuccess ? GUI.Style.Green : GUI.Style.Red * 0.5f;
|
||||||
|
progressBar.Color = ToolBox.GradientLerp(qteCooldown / qteCooldownTime, progressBar.Color, qteSliderColor, Color.White);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (qteTimer / qteTime <= item.Condition / item.MaxCondition)
|
||||||
|
{
|
||||||
|
qteSliderColor = Color.Lerp(qteSliderColor, GUI.Style.Green, 0.5f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
progressBar.Parent.Parent.Parent.DrawManually(spriteBatch, true);
|
||||||
|
GUI.DrawRectangle(spriteBatch,
|
||||||
|
new Rectangle(sliderRect.X + (int)((qteTimer / qteTime) * sliderRect.Width), sliderRect.Y - 5, 2, sliderRect.Height + 10),
|
||||||
|
qteSliderColor, true);
|
||||||
|
|
||||||
if (item.Condition > defaultMaxCondition)
|
if (item.Condition > defaultMaxCondition)
|
||||||
{
|
{
|
||||||
float extraCondition = item.MaxCondition * (item.MaxRepairConditionMultiplier - 1.0f);
|
float extraCondition = item.MaxCondition * (item.MaxRepairConditionMultiplier - 1.0f);
|
||||||
@@ -282,7 +334,7 @@ namespace Barotrauma.Items.Components
|
|||||||
progressBarOverlayText.Visible = false;
|
progressBarOverlayText.Visible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
RepairButton.Enabled = (currentFixerAction == FixActions.None || (CurrentFixer == character && currentFixerAction != FixActions.Repair)) && !item.IsFullCondition && IsBelowRepairThreshold;
|
RepairButton.Enabled = (currentFixerAction == FixActions.None || CurrentFixer == character) && !item.IsFullCondition;
|
||||||
RepairButton.Text = (currentFixerAction == FixActions.None || CurrentFixer != character || currentFixerAction != FixActions.Repair) ?
|
RepairButton.Text = (currentFixerAction == FixActions.None || CurrentFixer != character || currentFixerAction != FixActions.Repair) ?
|
||||||
repairButtonText :
|
repairButtonText :
|
||||||
repairingText + new string('.', ((int)(Timing.TotalTime * 2.0f) % 3) + 1);
|
repairingText + new string('.', ((int)(Timing.TotalTime * 2.0f) % 3) + 1);
|
||||||
@@ -352,6 +404,29 @@ namespace Barotrauma.Items.Components
|
|||||||
repairSoundChannel = null;
|
repairSoundChannel = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void QTEAction()
|
||||||
|
{
|
||||||
|
if (currentFixerAction == FixActions.Repair)
|
||||||
|
{
|
||||||
|
qteSuccess = qteCooldown <= 0.0f && qteTimer / qteTime <= item.Condition / item.MaxCondition;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GameMain.IsMultiplayer) { RepairBoost(qteSuccess); }
|
||||||
|
|
||||||
|
SoundPlayer.PlayUISound(qteSuccess ? GUISoundType.IncreaseQuantity : GUISoundType.DecreaseQuantity);
|
||||||
|
|
||||||
|
//on failure during cooldown reset cursor to beginning
|
||||||
|
if (!qteSuccess && qteCooldown > 0.0f) { qteTimer = qteTime; }
|
||||||
|
qteCooldown = qteCooldownTime;
|
||||||
|
//this will be set on button down so we can reset it here
|
||||||
|
requestStartFixAction = FixActions.None;
|
||||||
|
item.CreateClientEvent(this);
|
||||||
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
deteriorationTimer = msg.ReadSingle();
|
deteriorationTimer = msg.ReadSingle();
|
||||||
@@ -363,11 +438,13 @@ namespace Barotrauma.Items.Components
|
|||||||
currentFixerAction = (FixActions)msg.ReadRangedInteger(0, 2);
|
currentFixerAction = (FixActions)msg.ReadRangedInteger(0, 2);
|
||||||
CurrentFixer = currentFixerID != 0 ? Entity.FindEntityByID(currentFixerID) as Character : null;
|
CurrentFixer = currentFixerID != 0 ? Entity.FindEntityByID(currentFixerID) as Character : null;
|
||||||
item.MaxRepairConditionMultiplier = GetMaxRepairConditionMultiplier(CurrentFixer);
|
item.MaxRepairConditionMultiplier = GetMaxRepairConditionMultiplier(CurrentFixer);
|
||||||
|
repairBoost = msg.ReadSingle();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
||||||
{
|
{
|
||||||
msg.WriteRangedInteger((int)requestStartFixAction, 0, 2);
|
msg.WriteRangedInteger((int)requestStartFixAction, 0, 2);
|
||||||
|
msg.Write(qteSuccess);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,12 +26,7 @@ namespace Barotrauma.Items.Components
|
|||||||
AutoHideScrollBar = false
|
AutoHideScrollBar = false
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create fillerBlock to cover historyBox so new values appear at the bottom of historyBox
|
CreateFillerBlock();
|
||||||
// This could be removed if GUIListBox supported aligning its children
|
|
||||||
fillerBlock = new GUITextBlock(new RectTransform(new Vector2(1, 1), historyBox.Content.RectTransform, anchor: Anchor.TopCenter), string.Empty)
|
|
||||||
{
|
|
||||||
CanBeFocused = false
|
|
||||||
};
|
|
||||||
|
|
||||||
new GUIFrame(new RectTransform(new Vector2(0.9f, 0.01f), layoutGroup.RectTransform), style: "HorizontalLine");
|
new GUIFrame(new RectTransform(new Vector2(0.9f, 0.01f), layoutGroup.RectTransform), style: "HorizontalLine");
|
||||||
|
|
||||||
@@ -55,6 +50,16 @@ namespace Barotrauma.Items.Components
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create fillerBlock to cover historyBox so new values appear at the bottom of historyBox
|
||||||
|
// This could be removed if GUIListBox supported aligning its children
|
||||||
|
public void CreateFillerBlock()
|
||||||
|
{
|
||||||
|
fillerBlock = new GUITextBlock(new RectTransform(new Vector2(1, 1), historyBox.Content.RectTransform, anchor: Anchor.TopCenter), string.Empty)
|
||||||
|
{
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private void SendOutput(string input)
|
private void SendOutput(string input)
|
||||||
{
|
{
|
||||||
if (input.Length > MaxMessageLength)
|
if (input.Length > MaxMessageLength)
|
||||||
@@ -130,7 +135,12 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
||||||
{
|
{
|
||||||
msg.Write((string)extraData[2]);
|
if (extraData is null) { return; }
|
||||||
|
|
||||||
|
if (extraData[2] is string str)
|
||||||
|
{
|
||||||
|
msg.Write(str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
errorMsg += "\nTrying to dock the submarine to itself.";
|
errorMsg += "\nTrying to dock the submarine to itself.";
|
||||||
}
|
}
|
||||||
GameAnalyticsManager.AddErrorEventOnce("DockingPort.ClientRead:JointNotCreated", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("DockingPort.ClientRead:JointNotCreated", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLocked)
|
if (isLocked)
|
||||||
|
|||||||
@@ -1445,7 +1445,7 @@ namespace Barotrauma
|
|||||||
#else
|
#else
|
||||||
if (GameSettings.VerboseLogging) { DebugConsole.ThrowError(errorMsg); }
|
if (GameSettings.VerboseLogging) { DebugConsole.ThrowError(errorMsg); }
|
||||||
#endif
|
#endif
|
||||||
GameAnalyticsManager.AddErrorEventOnce("Item.ClientReadPosition:nophysicsbody", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("Item.ClientReadPosition:nophysicsbody", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1586,7 +1586,7 @@ namespace Barotrauma
|
|||||||
string errorMsg = "Failed to spawn item, prefab not found (name: " + (itemName ?? "null") + ", identifier: " + (itemIdentifier ?? "null") + ")";
|
string errorMsg = "Failed to spawn item, prefab not found (name: " + (itemName ?? "null") + ", identifier: " + (itemIdentifier ?? "null") + ")";
|
||||||
errorMsg += "\n" + string.Join(", ", GameMain.Config.AllEnabledPackages.Select(cp => cp.Name));
|
errorMsg += "\n" + string.Join(", ", GameMain.Config.AllEnabledPackages.Select(cp => cp.Name));
|
||||||
GameAnalyticsManager.AddErrorEventOnce("Item.ReadSpawnData:PrefabNotFound" + (itemName ?? "null") + (itemIdentifier ?? "null"),
|
GameAnalyticsManager.AddErrorEventOnce("Item.ReadSpawnData:PrefabNotFound" + (itemName ?? "null") + (itemIdentifier ?? "null"),
|
||||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Critical,
|
GameAnalyticsManager.ErrorSeverity.Critical,
|
||||||
errorMsg);
|
errorMsg);
|
||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg);
|
||||||
return null;
|
return null;
|
||||||
@@ -1607,7 +1607,7 @@ namespace Barotrauma
|
|||||||
string errorMsg =
|
string errorMsg =
|
||||||
$"Failed to spawn item \"{(itemIdentifier ?? "null")}\" in the inventory of \"{parentItem.prefab.Identifier} ({parentItem.ID})\" (component index out of range). Index: {itemContainerIndex}, components: {parentItem.components.Count}.";
|
$"Failed to spawn item \"{(itemIdentifier ?? "null")}\" in the inventory of \"{parentItem.prefab.Identifier} ({parentItem.ID})\" (component index out of range). Index: {itemContainerIndex}, components: {parentItem.components.Count}.";
|
||||||
GameAnalyticsManager.AddErrorEventOnce("Item.ReadSpawnData:ContainerIndexOutOfRange" + (itemName ?? "null") + (itemIdentifier ?? "null"),
|
GameAnalyticsManager.AddErrorEventOnce("Item.ReadSpawnData:ContainerIndexOutOfRange" + (itemName ?? "null") + (itemIdentifier ?? "null"),
|
||||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
GameAnalyticsManager.ErrorSeverity.Error,
|
||||||
errorMsg);
|
errorMsg);
|
||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg);
|
||||||
inventory = parentItem.GetComponent<ItemContainer>()?.Inventory;
|
inventory = parentItem.GetComponent<ItemContainer>()?.Inventory;
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ namespace Barotrauma
|
|||||||
private IEnumerable<CoroutineStatus> DimLight(LightSource light)
|
private IEnumerable<CoroutineStatus> DimLight(LightSource light)
|
||||||
{
|
{
|
||||||
float currBrightness = 1.0f;
|
float currBrightness = 1.0f;
|
||||||
while (light.Color.A > 0.0f && flashDuration > 0.0f)
|
while (light.Color.A > 0.0f && flashDuration > 0.0f && currBrightness > 0.0f)
|
||||||
{
|
{
|
||||||
light.Color = new Color(light.Color.R, light.Color.G, light.Color.B, (byte)(currBrightness * 255));
|
light.Color = new Color(light.Color.R, light.Color.G, light.Color.B, (byte)(currBrightness * 255));
|
||||||
currBrightness -= 1.0f / flashDuration * CoroutineManager.DeltaTime;
|
currBrightness -= 1.0f / flashDuration * CoroutineManager.DeltaTime;
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ namespace Barotrauma
|
|||||||
DebugConsole.ThrowError("Invalid left normal");
|
DebugConsole.ThrowError("Invalid left normal");
|
||||||
#endif
|
#endif
|
||||||
GameAnalyticsManager.AddErrorEventOnce("CaveGenerator.GenerateWallShapes:InvalidLeftNormal:" + level.Seed,
|
GameAnalyticsManager.AddErrorEventOnce("CaveGenerator.GenerateWallShapes:InvalidLeftNormal:" + level.Seed,
|
||||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Warning,
|
GameAnalyticsManager.ErrorSeverity.Warning,
|
||||||
"Invalid left normal (leftedge: " + leftEdge + ", rightedge: " + rightEdge + ", normal: " + leftNormal + ", seed: " + level.Seed + ")");
|
"Invalid left normal (leftedge: " + leftEdge + ", rightedge: " + rightEdge + ", normal: " + leftNormal + ", seed: " + level.Seed + ")");
|
||||||
|
|
||||||
if (cell.Body != null)
|
if (cell.Body != null)
|
||||||
@@ -127,7 +127,7 @@ namespace Barotrauma
|
|||||||
DebugConsole.ThrowError("Invalid right normal");
|
DebugConsole.ThrowError("Invalid right normal");
|
||||||
#endif
|
#endif
|
||||||
GameAnalyticsManager.AddErrorEventOnce("CaveGenerator.GenerateWallShapes:InvalidRightNormal:" + level.Seed,
|
GameAnalyticsManager.AddErrorEventOnce("CaveGenerator.GenerateWallShapes:InvalidRightNormal:" + level.Seed,
|
||||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Warning,
|
GameAnalyticsManager.ErrorSeverity.Warning,
|
||||||
"Invalid right normal (leftedge: " + leftEdge + ", rightedge: " + rightEdge + ", normal: " + rightNormal + ", seed: " + level.Seed + ")");
|
"Invalid right normal (leftedge: " + leftEdge + ", rightedge: " + rightEdge + ", normal: " + rightNormal + ", seed: " + level.Seed + ")");
|
||||||
|
|
||||||
if (cell.Body != null)
|
if (cell.Body != null)
|
||||||
|
|||||||
@@ -497,11 +497,13 @@ namespace Barotrauma.Lights
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly Dictionary<Hull, Rectangle> visibleHulls = new Dictionary<Hull, Rectangle>();
|
||||||
private Dictionary<Hull, Rectangle> GetVisibleHulls(Camera cam)
|
private Dictionary<Hull, Rectangle> GetVisibleHulls(Camera cam)
|
||||||
{
|
{
|
||||||
Dictionary<Hull, Rectangle> visibleHulls = new Dictionary<Hull, Rectangle>();
|
visibleHulls.Clear();
|
||||||
foreach (Hull hull in Hull.hullList)
|
foreach (Hull hull in Hull.hullList)
|
||||||
{
|
{
|
||||||
|
if (hull.HiddenInGame) { continue; }
|
||||||
var drawRect =
|
var drawRect =
|
||||||
hull.Submarine == null ?
|
hull.Submarine == null ?
|
||||||
hull.Rect :
|
hull.Rect :
|
||||||
|
|||||||
@@ -536,7 +536,7 @@ namespace Barotrauma
|
|||||||
invalidMessage = true;
|
invalidMessage = true;
|
||||||
string errorMsg = $"Error while reading a network event for the structure \"{Name} ({ID})\". Section count does not match (server: {sectionCount} client: {Sections.Length})";
|
string errorMsg = $"Error while reading a network event for the structure \"{Name} ({ID})\". Section count does not match (server: {sectionCount} client: {Sections.Length})";
|
||||||
DebugConsole.NewMessage(errorMsg, Color.Red);
|
DebugConsole.NewMessage(errorMsg, Color.Red);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("Structure.ClientRead:SectionCountMismatch", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("Structure.ClientRead:SectionCountMismatch", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < sectionCount; i++)
|
for (int i = 0; i < sectionCount; i++)
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
string errorMsg = "Error when loading round sound (" + element + ") - file path not set";
|
string errorMsg = "Error when loading round sound (" + element + ") - file path not set";
|
||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("Submarine.LoadRoundSound:FilePathEmpty" + element.ToString(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
|
GameAnalyticsManager.AddErrorEventOnce("Submarine.LoadRoundSound:FilePathEmpty" + element.ToString(), GameAnalyticsManager.ErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,7 +124,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
string errorMsg = "Failed to load sound file \"" + filename + "\".";
|
string errorMsg = "Failed to load sound file \"" + filename + "\".";
|
||||||
DebugConsole.ThrowError(errorMsg, e);
|
DebugConsole.ThrowError(errorMsg, e);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("Submarine.LoadRoundSound:FileNotFound" + filename, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
|
GameAnalyticsManager.AddErrorEventOnce("Submarine.LoadRoundSound:FileNotFound" + filename, GameAnalyticsManager.ErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -148,7 +148,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
string errorMsg = "Failed to load sound file \"" + roundSound.Filename + "\".";
|
string errorMsg = "Failed to load sound file \"" + roundSound.Filename + "\".";
|
||||||
DebugConsole.ThrowError(errorMsg, e);
|
DebugConsole.ThrowError(errorMsg, e);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("Submarine.LoadRoundSound:FileNotFound" + roundSound.Filename, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
|
GameAnalyticsManager.AddErrorEventOnce("Submarine.LoadRoundSound:FileNotFound" + roundSound.Filename, GameAnalyticsManager.ErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -183,13 +183,14 @@ namespace Barotrauma
|
|||||||
visibleSubs.Clear();
|
visibleSubs.Clear();
|
||||||
foreach (Submarine sub in Loaded)
|
foreach (Submarine sub in Loaded)
|
||||||
{
|
{
|
||||||
if (sub.WorldPosition.Y < Level.MaxEntityDepth) continue;
|
if (sub.WorldPosition.Y < Level.MaxEntityDepth) { continue; }
|
||||||
|
|
||||||
|
int margin = 500;
|
||||||
Rectangle worldBorders = new Rectangle(
|
Rectangle worldBorders = new Rectangle(
|
||||||
sub.Borders.X + (int)sub.WorldPosition.X - 500,
|
sub.VisibleBorders.X + (int)sub.WorldPosition.X - margin,
|
||||||
sub.Borders.Y + (int)sub.WorldPosition.Y + 500,
|
sub.VisibleBorders.Y + (int)sub.WorldPosition.Y + margin,
|
||||||
sub.Borders.Width + 1000,
|
sub.VisibleBorders.Width + margin * 2,
|
||||||
sub.Borders.Height + 1000);
|
sub.VisibleBorders.Height + margin * 2);
|
||||||
|
|
||||||
if (RectsOverlap(worldBorders, cam.WorldView))
|
if (RectsOverlap(worldBorders, cam.WorldView))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace Barotrauma
|
|||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Loading the preview image of the submarine \"" + Name + "\" failed. The file may be corrupted.", e);
|
DebugConsole.ThrowError("Loading the preview image of the submarine \"" + Name + "\" failed. The file may be corrupted.", e);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("Submarine..ctor:PreviewImageLoadingFailed", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
GameAnalyticsManager.AddErrorEventOnce("Submarine..ctor:PreviewImageLoadingFailed", GameAnalyticsManager.ErrorSeverity.Error,
|
||||||
"Loading the preview image of the submarine \"" + Name + "\" failed. The file may be corrupted.");
|
"Loading the preview image of the submarine \"" + Name + "\" failed. The file may be corrupted.");
|
||||||
PreviewImage = null;
|
PreviewImage = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -649,7 +649,7 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
errorMsg += "\nInner exception: " + e.InnerException.Message + "\n" + e.InnerException.StackTrace.CleanupStackTrace();
|
errorMsg += "\nInner exception: " + e.InnerException.Message + "\n" + e.InnerException.StackTrace.CleanupStackTrace();
|
||||||
}
|
}
|
||||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.Update:CheckServerMessagesException" + e.TargetSite.ToString(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("GameClient.Update:CheckServerMessagesException" + e.TargetSite.ToString(), GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
DebugConsole.ThrowError("Error while reading a message from server.", e);
|
DebugConsole.ThrowError("Error while reading a message from server.", e);
|
||||||
new GUIMessageBox(TextManager.Get("Error"), TextManager.GetWithVariables("MessageReadError", new string[2] { "[message]", "[targetsite]" }, new string[2] { e.Message, e.TargetSite.ToString() }));
|
new GUIMessageBox(TextManager.Get("Error"), TextManager.GetWithVariables("MessageReadError", new string[2] { "[message]", "[targetsite]" }, new string[2] { e.Message, e.TargetSite.ToString() }));
|
||||||
Disconnect();
|
Disconnect();
|
||||||
@@ -779,7 +779,7 @@ namespace Barotrauma.Networking
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
DebugConsole.ThrowError("Error while reading an ingame update message from server.", e);
|
DebugConsole.ThrowError("Error while reading an ingame update message from server.", e);
|
||||||
#endif
|
#endif
|
||||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.ReadDataMessage:ReadIngameUpdate", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("GameClient.ReadDataMessage:ReadIngameUpdate", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -791,7 +791,7 @@ namespace Barotrauma.Networking
|
|||||||
errorMsg += "\n" + Environment.StackTrace.CleanupStackTrace();
|
errorMsg += "\n" + Environment.StackTrace.CleanupStackTrace();
|
||||||
GameAnalyticsManager.AddErrorEventOnce(
|
GameAnalyticsManager.AddErrorEventOnce(
|
||||||
"GameClient.ReadDataMessage:VoipClientNull",
|
"GameClient.ReadDataMessage:VoipClientNull",
|
||||||
GameMain.Client == null ? GameAnalyticsSDK.Net.EGAErrorSeverity.Error : GameAnalyticsSDK.Net.EGAErrorSeverity.Warning,
|
GameMain.Client == null ? GameAnalyticsManager.ErrorSeverity.Error : GameAnalyticsManager.ErrorSeverity.Warning,
|
||||||
errorMsg);
|
errorMsg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -989,7 +989,7 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
string errorMsg = "Submarine equality check failed. The submarine loaded at your end doesn't match the one loaded by the server." +
|
string errorMsg = "Submarine equality check failed. The submarine loaded at your end doesn't match the one loaded by the server." +
|
||||||
" There may have been an error in receiving the up-to-date submarine file from the server.";
|
" There may have been an error in receiving the up-to-date submarine file from the server.";
|
||||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:SubsDontMatch" + Level.Loaded.Seed, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:SubsDontMatch" + Level.Loaded.Seed, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
throw new Exception(errorMsg);
|
throw new Exception(errorMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1010,7 +1010,7 @@ namespace Barotrauma.Networking
|
|||||||
if (!GameMain.GameSession.Missions.Select(m => m.Prefab.Identifier).OrderBy(id => id).SequenceEqual(serverMissionIdentifiers.OrderBy(id => id)))
|
if (!GameMain.GameSession.Missions.Select(m => m.Prefab.Identifier).OrderBy(id => id).SequenceEqual(serverMissionIdentifiers.OrderBy(id => id)))
|
||||||
{
|
{
|
||||||
string errorMsg = $"Mission equality check failed. The mission selected at your end doesn't match the one loaded by the server (server: {string.Join(", ", serverMissionIdentifiers)}, client: {string.Join(", ", GameMain.GameSession.Missions.Select(m => m.Prefab.Identifier))})";
|
string errorMsg = $"Mission equality check failed. The mission selected at your end doesn't match the one loaded by the server (server: {string.Join(", ", serverMissionIdentifiers)}, client: {string.Join(", ", GameMain.GameSession.Missions.Select(m => m.Prefab.Identifier))})";
|
||||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:MissionsDontMatch" + Level.Loaded.Seed, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:MissionsDontMatch" + Level.Loaded.Seed, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
throw new Exception(errorMsg);
|
throw new Exception(errorMsg);
|
||||||
}
|
}
|
||||||
GameMain.GameSession.EnforceMissionOrder(serverMissionIdentifiers);
|
GameMain.GameSession.EnforceMissionOrder(serverMissionIdentifiers);
|
||||||
@@ -1031,7 +1031,7 @@ namespace Barotrauma.Networking
|
|||||||
", seed: " + Level.Loaded.Seed +
|
", seed: " + Level.Loaded.Seed +
|
||||||
", sub: " + Submarine.MainSub.Info.Name + " (" + Submarine.MainSub.Info.MD5Hash.ShortHash + ")" +
|
", sub: " + Submarine.MainSub.Info.Name + " (" + Submarine.MainSub.Info.MD5Hash.ShortHash + ")" +
|
||||||
", mirrored: " + Level.Loaded.Mirrored + ").";
|
", mirrored: " + Level.Loaded.Mirrored + ").";
|
||||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:LevelsDontMatch" + Level.Loaded.Seed, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:LevelsDontMatch" + Level.Loaded.Seed, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
throw new Exception(errorMsg);
|
throw new Exception(errorMsg);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1047,7 +1047,7 @@ namespace Barotrauma.Networking
|
|||||||
", seed: " + Level.Loaded.Seed +
|
", seed: " + Level.Loaded.Seed +
|
||||||
", sub: " + Submarine.MainSub.Info.Name + " (" + Submarine.MainSub.Info.MD5Hash.ShortHash + ")" +
|
", sub: " + Submarine.MainSub.Info.Name + " (" + Submarine.MainSub.Info.MD5Hash.ShortHash + ")" +
|
||||||
", mirrored: " + Level.Loaded.Mirrored + ").";
|
", mirrored: " + Level.Loaded.Mirrored + ").";
|
||||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:LevelsDontMatch" + Level.Loaded.Seed, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:LevelsDontMatch" + Level.Loaded.Seed, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
throw new Exception(errorMsg);
|
throw new Exception(errorMsg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1117,8 +1117,8 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
GameAnalyticsManager.AddErrorEventOnce(
|
GameAnalyticsManager.AddErrorEventOnce(
|
||||||
"GameClient.HandleDisconnectMessage",
|
"GameClient.HandleDisconnectMessage",
|
||||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Debug,
|
GameAnalyticsManager.ErrorSeverity.Debug,
|
||||||
"Client received a disconnect message. Reason: " + disconnectReason.ToString() + ", message: " + disconnectMsg);
|
"Client received a disconnect message. Reason: " + disconnectReason.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (disconnectReason == DisconnectReason.ServerFull)
|
if (disconnectReason == DisconnectReason.ServerFull)
|
||||||
@@ -1532,7 +1532,7 @@ namespace Barotrauma.Networking
|
|||||||
gameStarted = true;
|
gameStarted = true;
|
||||||
GameMain.NetLobbyScreen.Select();
|
GameMain.NetLobbyScreen.Select();
|
||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:FailedToSelectSub" + subName, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:FailedToSelectSub" + subName, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
roundInitStatus = RoundInitStatus.Interrupted;
|
roundInitStatus = RoundInitStatus.Interrupted;
|
||||||
yield return CoroutineStatus.Failure;
|
yield return CoroutineStatus.Failure;
|
||||||
}
|
}
|
||||||
@@ -1544,7 +1544,7 @@ namespace Barotrauma.Networking
|
|||||||
GameMain.NetLobbyScreen.Select();
|
GameMain.NetLobbyScreen.Select();
|
||||||
string errorMsg = "Failed to select shuttle \"" + shuttleName + "\" (hash: " + shuttleHash + ").";
|
string errorMsg = "Failed to select shuttle \"" + shuttleName + "\" (hash: " + shuttleHash + ").";
|
||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:FailedToSelectShuttle" + shuttleName, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:FailedToSelectShuttle" + shuttleName, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
roundInitStatus = RoundInitStatus.Interrupted;
|
roundInitStatus = RoundInitStatus.Interrupted;
|
||||||
yield return CoroutineStatus.Failure;
|
yield return CoroutineStatus.Failure;
|
||||||
}
|
}
|
||||||
@@ -2116,9 +2116,6 @@ namespace Barotrauma.Networking
|
|||||||
bool autoRestartEnabled = inc.ReadBoolean();
|
bool autoRestartEnabled = inc.ReadBoolean();
|
||||||
float autoRestartTimer = autoRestartEnabled ? inc.ReadSingle() : 0.0f;
|
float autoRestartTimer = autoRestartEnabled ? inc.ReadSingle() : 0.0f;
|
||||||
|
|
||||||
bool radiationEnabled = inc.ReadBoolean();
|
|
||||||
byte maxMissionCount = inc.ReadByte();
|
|
||||||
|
|
||||||
//ignore the message if we already a more up-to-date one
|
//ignore the message if we already a more up-to-date one
|
||||||
//or if we're still waiting for the initial update
|
//or if we're still waiting for the initial update
|
||||||
if (NetIdUtils.IdMoreRecent(updateID, GameMain.NetLobbyScreen.LastUpdateID) &&
|
if (NetIdUtils.IdMoreRecent(updateID, GameMain.NetLobbyScreen.LastUpdateID) &&
|
||||||
@@ -2168,22 +2165,15 @@ namespace Barotrauma.Networking
|
|||||||
if (GameMain.NetLobbyScreen.CheckIfCampaignSubMatches(sub, "campaign"))
|
if (GameMain.NetLobbyScreen.CheckIfCampaignSubMatches(sub, "campaign"))
|
||||||
{
|
{
|
||||||
GameMain.NetLobbyScreen.CampaignSubmarines.Add(sub);
|
GameMain.NetLobbyScreen.CampaignSubmarines.Add(sub);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (HasPermission(ClientPermissions.ManageCampaign) && !gameStarted && GameMain.NetLobbyScreen?.CampaignSetupUI != null)
|
|
||||||
{
|
|
||||||
GameMain.NetLobbyScreen.CampaignSetupUI.RefreshMultiplayerCampaignSubUI(GameMain.NetLobbyScreen.CampaignSubmarines);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GameMain.NetLobbyScreen.SetAllowSpectating(allowSpectating);
|
GameMain.NetLobbyScreen.SetAllowSpectating(allowSpectating);
|
||||||
GameMain.NetLobbyScreen.LevelSeed = levelSeed;
|
GameMain.NetLobbyScreen.LevelSeed = levelSeed;
|
||||||
GameMain.NetLobbyScreen.SetLevelDifficulty(levelDifficulty);
|
GameMain.NetLobbyScreen.SetLevelDifficulty(levelDifficulty);
|
||||||
GameMain.NetLobbyScreen.SetRadiationEnabled(radiationEnabled);
|
|
||||||
GameMain.NetLobbyScreen.SetBotSpawnMode(botSpawnMode);
|
GameMain.NetLobbyScreen.SetBotSpawnMode(botSpawnMode);
|
||||||
GameMain.NetLobbyScreen.SetBotCount(botCount);
|
GameMain.NetLobbyScreen.SetBotCount(botCount);
|
||||||
GameMain.NetLobbyScreen.SetMaxMissionCount(maxMissionCount);
|
|
||||||
GameMain.NetLobbyScreen.SetAutoRestart(autoRestartEnabled, autoRestartTimer);
|
GameMain.NetLobbyScreen.SetAutoRestart(autoRestartEnabled, autoRestartTimer);
|
||||||
|
|
||||||
serverSettings.VoiceChatEnabled = voiceChatEnabled;
|
serverSettings.VoiceChatEnabled = voiceChatEnabled;
|
||||||
@@ -2355,7 +2345,7 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
errorLines.Add("[" + DebugConsole.Messages[i].Time + "] " + DebugConsole.Messages[i].Text);
|
errorLines.Add("[" + DebugConsole.Messages[i].Time + "] " + DebugConsole.Messages[i].Text);
|
||||||
}
|
}
|
||||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.ReadInGameUpdate", GameAnalyticsSDK.Net.EGAErrorSeverity.Critical, string.Join("\n", errorLines));
|
GameAnalyticsManager.AddErrorEventOnce("GameClient.ReadInGameUpdate", GameAnalyticsManager.ErrorSeverity.Critical, string.Join("\n", errorLines));
|
||||||
|
|
||||||
DebugConsole.ThrowError("Writing object data to \"networkerror_data.log\", please send this file to us at http://github.com/Regalis11/Barotrauma/issues");
|
DebugConsole.ThrowError("Writing object data to \"networkerror_data.log\", please send this file to us at http://github.com/Regalis11/Barotrauma/issues");
|
||||||
|
|
||||||
@@ -2591,29 +2581,29 @@ namespace Barotrauma.Networking
|
|||||||
subElement.ToolTip = newSub.Description;
|
subElement.ToolTip = newSub.Description;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameMain.NetLobbyScreen.FailedSelectedSub != null &&
|
if (GameMain.NetLobbyScreen.FailedSelectedSub.HasValue &&
|
||||||
GameMain.NetLobbyScreen.FailedSelectedSub.First == newSub.Name &&
|
GameMain.NetLobbyScreen.FailedSelectedSub.Value.Name == newSub.Name &&
|
||||||
GameMain.NetLobbyScreen.FailedSelectedSub.Second == newSub.MD5Hash.Hash)
|
GameMain.NetLobbyScreen.FailedSelectedSub.Value.Hash == newSub.MD5Hash.Hash)
|
||||||
{
|
{
|
||||||
GameMain.NetLobbyScreen.TrySelectSub(newSub.Name, newSub.MD5Hash.Hash, GameMain.NetLobbyScreen.SubList);
|
GameMain.NetLobbyScreen.TrySelectSub(newSub.Name, newSub.MD5Hash.Hash, GameMain.NetLobbyScreen.SubList);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameMain.NetLobbyScreen.FailedSelectedShuttle != null &&
|
if (GameMain.NetLobbyScreen.FailedSelectedShuttle.HasValue &&
|
||||||
GameMain.NetLobbyScreen.FailedSelectedShuttle.First == newSub.Name &&
|
GameMain.NetLobbyScreen.FailedSelectedShuttle.Value.Name == newSub.Name &&
|
||||||
GameMain.NetLobbyScreen.FailedSelectedShuttle.Second == newSub.MD5Hash.Hash)
|
GameMain.NetLobbyScreen.FailedSelectedShuttle.Value.Hash == newSub.MD5Hash.Hash)
|
||||||
{
|
{
|
||||||
GameMain.NetLobbyScreen.TrySelectSub(newSub.Name, newSub.MD5Hash.Hash, GameMain.NetLobbyScreen.ShuttleList.ListBox);
|
GameMain.NetLobbyScreen.TrySelectSub(newSub.Name, newSub.MD5Hash.Hash, GameMain.NetLobbyScreen.ShuttleList.ListBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pair<string, string> failedCampaignSub = GameMain.NetLobbyScreen.FailedCampaignSubs.Find(s => s.First == newSub.Name && s.Second == newSub.MD5Hash.Hash);
|
NetLobbyScreen.FailedSubInfo failedCampaignSub = GameMain.NetLobbyScreen.FailedCampaignSubs.Find(s => s.Name == newSub.Name && s.Hash == newSub.MD5Hash.Hash);
|
||||||
if (failedCampaignSub != null)
|
if (failedCampaignSub != default)
|
||||||
{
|
{
|
||||||
GameMain.NetLobbyScreen.CampaignSubmarines.Add(newSub);
|
GameMain.NetLobbyScreen.CampaignSubmarines.Add(newSub);
|
||||||
GameMain.NetLobbyScreen.FailedCampaignSubs.Remove(failedCampaignSub);
|
GameMain.NetLobbyScreen.FailedCampaignSubs.Remove(failedCampaignSub);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pair<string, string> failedOwnedSub = GameMain.NetLobbyScreen.FailedOwnedSubs.Find(s => s.First == newSub.Name && s.Second == newSub.MD5Hash.Hash);
|
NetLobbyScreen.FailedSubInfo failedOwnedSub = GameMain.NetLobbyScreen.FailedOwnedSubs.Find(s => s.Name == newSub.Name && s.Hash == newSub.MD5Hash.Hash);
|
||||||
if (failedOwnedSub != null)
|
if (failedOwnedSub != default)
|
||||||
{
|
{
|
||||||
GameMain.NetLobbyScreen.ServerOwnedSubmarines.Add(newSub);
|
GameMain.NetLobbyScreen.ServerOwnedSubmarines.Add(newSub);
|
||||||
GameMain.NetLobbyScreen.FailedOwnedSubs.Remove(failedOwnedSub);
|
GameMain.NetLobbyScreen.FailedOwnedSubs.Remove(failedOwnedSub);
|
||||||
@@ -2946,7 +2936,6 @@ namespace Barotrauma.Networking
|
|||||||
IWriteMessage msg = new WriteOnlyMessage();
|
IWriteMessage msg = new WriteOnlyMessage();
|
||||||
msg.Write((byte)ClientPacketHeader.SERVER_COMMAND);
|
msg.Write((byte)ClientPacketHeader.SERVER_COMMAND);
|
||||||
msg.Write((UInt16)ClientPermissions.SelectSub);
|
msg.Write((UInt16)ClientPermissions.SelectSub);
|
||||||
msg.Write(false);
|
|
||||||
msg.Write(isShuttle); msg.WritePadBits();
|
msg.Write(isShuttle); msg.WritePadBits();
|
||||||
msg.Write((UInt16)subIndex);
|
msg.Write((UInt16)subIndex);
|
||||||
msg.Write((byte)ServerNetObject.END_OF_MESSAGE);
|
msg.Write((byte)ServerNetObject.END_OF_MESSAGE);
|
||||||
@@ -2954,23 +2943,6 @@ namespace Barotrauma.Networking
|
|||||||
clientPeer.Send(msg, DeliveryMethod.Reliable);
|
clientPeer.Send(msg, DeliveryMethod.Reliable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tell the server to add / remove a purchasable submarine (permission required)
|
|
||||||
/// </summary>
|
|
||||||
public void RequestCampaignSub(SubmarineInfo sub, bool add)
|
|
||||||
{
|
|
||||||
if (!HasPermission(ClientPermissions.SelectSub) || sub == null) return;
|
|
||||||
IWriteMessage msg = new WriteOnlyMessage();
|
|
||||||
msg.Write((byte)ClientPacketHeader.SERVER_COMMAND);
|
|
||||||
msg.Write((UInt16)ClientPermissions.SelectSub);
|
|
||||||
msg.Write(true);
|
|
||||||
msg.Write(sub.EqualityCheckVal);
|
|
||||||
msg.Write(add);
|
|
||||||
msg.Write((byte)ServerNetObject.END_OF_MESSAGE);
|
|
||||||
|
|
||||||
clientPeer.Send(msg, DeliveryMethod.Reliable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tell the server to select a mode (permission required)
|
/// Tell the server to select a mode (permission required)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg);
|
||||||
|
|
||||||
GameAnalyticsManager.AddErrorEventOnce("ClientEntityEventManager.Read:BitPosMismatch", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("ClientEntityEventManager.Read:BitPosMismatch", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
|
|
||||||
//TODO: force the BitPosition to correct place? Having some entity in a potentially incorrect state is not as bad as a desync kick
|
//TODO: force the BitPosition to correct place? Having some entity in a potentially incorrect state is not as bad as a desync kick
|
||||||
//msg.BitPosition = (int)(msgPosition + msgLength * 8);
|
//msg.BitPosition = (int)(msgPosition + msgLength * 8);
|
||||||
@@ -252,7 +252,7 @@ namespace Barotrauma.Networking
|
|||||||
DebugConsole.ThrowError("Failed to read event for entity \"" + entity.ToString() + "\"!", e);
|
DebugConsole.ThrowError("Failed to read event for entity \"" + entity.ToString() + "\"!", e);
|
||||||
|
|
||||||
GameAnalyticsManager.AddErrorEventOnce("ClientEntityEventManager.Read:ReadFailed" + entity.ToString(),
|
GameAnalyticsManager.AddErrorEventOnce("ClientEntityEventManager.Read:ReadFailed" + entity.ToString(),
|
||||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
msg.BitPosition = (int)(msgPosition + msgLength * 8);
|
msg.BitPosition = (int)(msgPosition + msgLength * 8);
|
||||||
msg.ReadPadBits();
|
msg.ReadPadBits();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,13 +115,11 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
if (!isActive) { return; }
|
if (!isActive) { return; }
|
||||||
|
|
||||||
byte incByte = inc.ReadByte();
|
PacketHeader packetHeader = (PacketHeader)inc.ReadByte();
|
||||||
bool isCompressed = (incByte & (byte)PacketHeader.IsCompressed) != 0;
|
|
||||||
bool isConnectionInitializationStep = (incByte & (byte)PacketHeader.IsConnectionInitializationStep) != 0;
|
|
||||||
|
|
||||||
//Console.WriteLine(isCompressed + " " + isConnectionInitializationStep + " " + (int)incByte);
|
//Console.WriteLine(isCompressed + " " + isConnectionInitializationStep + " " + (int)incByte);
|
||||||
|
|
||||||
if (isConnectionInitializationStep && initializationStep != ConnectionInitialization.Success)
|
if (packetHeader.IsConnectionInitializationStep() && initializationStep != ConnectionInitialization.Success)
|
||||||
{
|
{
|
||||||
ReadConnectionInitializationStep(new ReadWriteMessage(inc.Data, (int)inc.Position, inc.LengthBits, false));
|
ReadConnectionInitializationStep(new ReadWriteMessage(inc.Data, (int)inc.Position, inc.LengthBits, false));
|
||||||
}
|
}
|
||||||
@@ -133,7 +131,7 @@ namespace Barotrauma.Networking
|
|||||||
initializationStep = ConnectionInitialization.Success;
|
initializationStep = ConnectionInitialization.Success;
|
||||||
}
|
}
|
||||||
UInt16 length = inc.ReadUInt16();
|
UInt16 length = inc.ReadUInt16();
|
||||||
IReadMessage msg = new ReadOnlyMessage(inc.Data, isCompressed, inc.PositionInBytes, length, ServerConnection);
|
IReadMessage msg = new ReadOnlyMessage(inc.Data, packetHeader.IsCompressed(), inc.PositionInBytes, length, ServerConnection);
|
||||||
OnMessageReceived?.Invoke(msg);
|
OnMessageReceived?.Invoke(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,33 +112,28 @@ namespace Barotrauma.Networking
|
|||||||
NetworkConnection.TimeoutThresholdInGame :
|
NetworkConnection.TimeoutThresholdInGame :
|
||||||
NetworkConnection.TimeoutThreshold;
|
NetworkConnection.TimeoutThreshold;
|
||||||
|
|
||||||
byte incByte = data[0];
|
PacketHeader packetHeader = (PacketHeader)data[0];
|
||||||
bool isCompressed = (incByte & (byte)PacketHeader.IsCompressed) != 0;
|
|
||||||
bool isConnectionInitializationStep = (incByte & (byte)PacketHeader.IsConnectionInitializationStep) != 0;
|
|
||||||
bool isDisconnectMessage = (incByte & (byte)PacketHeader.IsDisconnectMessage) != 0;
|
|
||||||
bool isServerMessage = (incByte & (byte)PacketHeader.IsServerMessage) != 0;
|
|
||||||
bool isHeartbeatMessage = (incByte & (byte)PacketHeader.IsHeartbeatMessage) != 0;
|
|
||||||
|
|
||||||
if (!isServerMessage) { return; }
|
if (!packetHeader.IsServerMessage()) { return; }
|
||||||
|
|
||||||
if (isConnectionInitializationStep)
|
if (packetHeader.IsConnectionInitializationStep())
|
||||||
{
|
{
|
||||||
ulong low = Lidgren.Network.NetBitWriter.ReadUInt32(data, 32, 8);
|
ulong low = Lidgren.Network.NetBitWriter.ReadUInt32(data, 32, 8);
|
||||||
ulong high = Lidgren.Network.NetBitWriter.ReadUInt32(data, 32, 8 + 32);
|
ulong high = Lidgren.Network.NetBitWriter.ReadUInt32(data, 32, 8 + 32);
|
||||||
ulong lobbyId = low + (high << 32);
|
ulong lobbyId = low + (high << 32);
|
||||||
|
|
||||||
Steam.SteamManager.JoinLobby(lobbyId, false);
|
Steam.SteamManager.JoinLobby(lobbyId, false);
|
||||||
IReadMessage inc = new ReadOnlyMessage(data, false, 1 + 8, dataLength - 9, ServerConnection);
|
IReadMessage inc = new ReadOnlyMessage(data, false, 1 + 8, dataLength - (1 + 8), ServerConnection);
|
||||||
if (initializationStep != ConnectionInitialization.Success)
|
if (initializationStep != ConnectionInitialization.Success)
|
||||||
{
|
{
|
||||||
incomingInitializationMessages.Add(inc);
|
incomingInitializationMessages.Add(inc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (isHeartbeatMessage)
|
else if (packetHeader.IsHeartbeatMessage())
|
||||||
{
|
{
|
||||||
return; //TODO: implement heartbeats
|
return; //TODO: implement heartbeats
|
||||||
}
|
}
|
||||||
else if (isDisconnectMessage)
|
else if (packetHeader.IsDisconnectMessage())
|
||||||
{
|
{
|
||||||
IReadMessage inc = new ReadOnlyMessage(data, false, 1, dataLength - 1, ServerConnection);
|
IReadMessage inc = new ReadOnlyMessage(data, false, 1, dataLength - 1, ServerConnection);
|
||||||
string msg = inc.ReadString();
|
string msg = inc.ReadString();
|
||||||
@@ -147,10 +142,9 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UInt16 length = data[1];
|
UInt16 length = Lidgren.Network.NetBitWriter.ReadUInt16(data, 16, 8);
|
||||||
length |= (UInt16)(((UInt32)data[2]) << 8);
|
|
||||||
|
|
||||||
IReadMessage inc = new ReadOnlyMessage(data, isCompressed, 3, length, ServerConnection);
|
IReadMessage inc = new ReadOnlyMessage(data, packetHeader.IsCompressed(), 3, length, ServerConnection);
|
||||||
incomingDataMessages.Add(inc);
|
incomingDataMessages.Add(inc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,18 +147,13 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
DeliveryMethod deliveryMethod = (DeliveryMethod)data[0];
|
DeliveryMethod deliveryMethod = (DeliveryMethod)data[0];
|
||||||
|
|
||||||
byte incByte = data[1];
|
PacketHeader packetHeader = (PacketHeader)data[1];
|
||||||
bool isCompressed = (incByte & (byte)PacketHeader.IsCompressed) != 0;
|
|
||||||
bool isConnectionInitializationStep = (incByte & (byte)PacketHeader.IsConnectionInitializationStep) != 0;
|
|
||||||
bool isDisconnectMessage = (incByte & (byte)PacketHeader.IsDisconnectMessage) != 0;
|
|
||||||
bool isServerMessage = (incByte & (byte)PacketHeader.IsServerMessage) != 0;
|
|
||||||
bool isHeartbeatMessage = (incByte & (byte)PacketHeader.IsHeartbeatMessage) != 0;
|
|
||||||
|
|
||||||
if (!remotePeer.Authenticated & !remotePeer.Authenticating && isConnectionInitializationStep)
|
if (!remotePeer.Authenticated & !remotePeer.Authenticating && packetHeader.IsConnectionInitializationStep())
|
||||||
{
|
{
|
||||||
remotePeer.DisconnectTime = null;
|
remotePeer.DisconnectTime = null;
|
||||||
|
|
||||||
IReadMessage authMsg = new ReadOnlyMessage(data, isCompressed, 2, dataLength - 2, null);
|
IReadMessage authMsg = new ReadOnlyMessage(data, packetHeader.IsCompressed(), 2, dataLength - 2, null);
|
||||||
ConnectionInitialization initializationStep = (ConnectionInitialization)authMsg.ReadByte();
|
ConnectionInitialization initializationStep = (ConnectionInitialization)authMsg.ReadByte();
|
||||||
if (initializationStep == ConnectionInitialization.SteamTicketAndVersion)
|
if (initializationStep == ConnectionInitialization.SteamTicketAndVersion)
|
||||||
{
|
{
|
||||||
@@ -242,17 +237,11 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
int p2pDataStart = inc.BytePosition;
|
int p2pDataStart = inc.BytePosition;
|
||||||
|
|
||||||
byte incByte = inc.ReadByte();
|
PacketHeader packetHeader = (PacketHeader)inc.ReadByte();
|
||||||
|
|
||||||
bool isCompressed = (incByte & (byte)PacketHeader.IsCompressed) != 0;
|
|
||||||
bool isConnectionInitializationStep = (incByte & (byte)PacketHeader.IsConnectionInitializationStep) != 0;
|
|
||||||
bool isDisconnectMessage = (incByte & (byte)PacketHeader.IsDisconnectMessage) != 0;
|
|
||||||
bool isServerMessage = (incByte & (byte)PacketHeader.IsServerMessage) != 0;
|
|
||||||
bool isHeartbeatMessage = (incByte & (byte)PacketHeader.IsHeartbeatMessage) != 0;
|
|
||||||
|
|
||||||
if (recipientSteamId != selfSteamID)
|
if (recipientSteamId != selfSteamID)
|
||||||
{
|
{
|
||||||
if (!isServerMessage)
|
if (!packetHeader.IsServerMessage())
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Received non-server message meant for remote peer");
|
DebugConsole.ThrowError("Received non-server message meant for remote peer");
|
||||||
return;
|
return;
|
||||||
@@ -262,7 +251,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
if (peer == null) { return; }
|
if (peer == null) { return; }
|
||||||
|
|
||||||
if (isDisconnectMessage)
|
if (packetHeader.IsDisconnectMessage())
|
||||||
{
|
{
|
||||||
DisconnectPeer(peer, inc.ReadString());
|
DisconnectPeer(peer, inc.ReadString());
|
||||||
return;
|
return;
|
||||||
@@ -273,8 +262,8 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
case DeliveryMethod.Reliable:
|
case DeliveryMethod.Reliable:
|
||||||
case DeliveryMethod.ReliableOrdered:
|
case DeliveryMethod.ReliableOrdered:
|
||||||
//the documentation seems to suggest that the Reliable send type
|
//the documentation seems to suggest that the
|
||||||
//enforces packet order (TODO: verify)
|
//Reliable send type enforces packet order
|
||||||
sendType = Steamworks.P2PSend.Reliable;
|
sendType = Steamworks.P2PSend.Reliable;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -284,17 +273,31 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
byte[] p2pData;
|
byte[] p2pData;
|
||||||
|
|
||||||
if (isConnectionInitializationStep)
|
if (packetHeader.IsConnectionInitializationStep())
|
||||||
{
|
{
|
||||||
p2pData = new byte[inc.LengthBytes - p2pDataStart + 8];
|
p2pData = new byte[inc.LengthBytes - p2pDataStart + 8];
|
||||||
p2pData[0] = inc.Buffer[p2pDataStart];
|
p2pData[0] = inc.Buffer[p2pDataStart];
|
||||||
Lidgren.Network.NetBitWriter.WriteUInt64(SteamManager.CurrentLobbyID, 64, p2pData, 8);
|
Lidgren.Network.NetBitWriter.WriteUInt64(SteamManager.CurrentLobbyID, 8 * 8, p2pData, 1 * 8);
|
||||||
Array.Copy(inc.Buffer, p2pDataStart+1, p2pData, 9, inc.LengthBytes - p2pDataStart - 1);
|
Array.Copy(inc.Buffer, p2pDataStart+1, p2pData, 1 + 8, inc.LengthBytes - p2pDataStart - 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
p2pData = new byte[inc.LengthBytes - p2pDataStart];
|
p2pData = new byte[inc.LengthBytes - p2pDataStart];
|
||||||
Array.Copy(inc.Buffer, p2pDataStart, p2pData, 0, p2pData.Length);
|
Array.Copy(inc.Buffer, p2pDataStart, p2pData, 0, p2pData.Length);
|
||||||
|
|
||||||
|
if (!packetHeader.IsHeartbeatMessage() && !packetHeader.IsDisconnectMessage())
|
||||||
|
{
|
||||||
|
UInt16 length = Lidgren.Network.NetBitWriter.ReadUInt16(p2pData, 16, 8);
|
||||||
|
if (length > p2pData.Length - 2)
|
||||||
|
{
|
||||||
|
string errorMsg = $"Length written in message to send to client is larger than buffer size ({length} > {p2pData.Length - 2})";
|
||||||
|
DebugConsole.ThrowError(errorMsg);
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce(
|
||||||
|
"SteamP2POwnerPeerLengthValidationFail",
|
||||||
|
GameAnalyticsManager.ErrorSeverity.Error,
|
||||||
|
errorMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p2pData.Length + 4 >= MsgConstants.MTU)
|
if (p2pData.Length + 4 >= MsgConstants.MTU)
|
||||||
@@ -323,21 +326,21 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (isDisconnectMessage)
|
if (packetHeader.IsDisconnectMessage())
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Received disconnect message from owned server");
|
DebugConsole.ThrowError("Received disconnect message from owned server");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!isServerMessage)
|
if (!packetHeader.IsServerMessage())
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Received non-server message from owned server");
|
DebugConsole.ThrowError("Received non-server message from owned server");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (isHeartbeatMessage)
|
if (packetHeader.IsHeartbeatMessage())
|
||||||
{
|
{
|
||||||
return; //timeout is handled by Lidgren, ignore this message
|
return; //no timeout since we're using pipes, ignore this message
|
||||||
}
|
}
|
||||||
if (isConnectionInitializationStep)
|
if (packetHeader.IsConnectionInitializationStep())
|
||||||
{
|
{
|
||||||
IWriteMessage outMsg = new WriteOnlyMessage();
|
IWriteMessage outMsg = new WriteOnlyMessage();
|
||||||
outMsg.Write(selfSteamID);
|
outMsg.Write(selfSteamID);
|
||||||
@@ -358,7 +361,7 @@ namespace Barotrauma.Networking
|
|||||||
initializationStep = ConnectionInitialization.Success;
|
initializationStep = ConnectionInitialization.Success;
|
||||||
}
|
}
|
||||||
UInt16 length = inc.ReadUInt16();
|
UInt16 length = inc.ReadUInt16();
|
||||||
IReadMessage msg = new ReadOnlyMessage(inc.Buffer, isCompressed, inc.BytePosition, length, ServerConnection);
|
IReadMessage msg = new ReadOnlyMessage(inc.Buffer, packetHeader.IsCompressed(), inc.BytePosition, length, ServerConnection);
|
||||||
OnMessageReceived?.Invoke(msg);
|
OnMessageReceived?.Invoke(msg);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -242,7 +242,8 @@ namespace Barotrauma.Networking
|
|||||||
textBlock.ClickableAreas.Add(new GUITextBlock.ClickableArea()
|
textBlock.ClickableAreas.Add(new GUITextBlock.ClickableArea()
|
||||||
{
|
{
|
||||||
Data = data,
|
Data = data,
|
||||||
OnClick = GameMain.NetLobbyScreen.SelectPlayer
|
OnClick = GameMain.NetLobbyScreen.SelectPlayer,
|
||||||
|
OnSecondaryClick = GameMain.NetLobbyScreen.ShowPlayerContextMenu
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,8 +92,9 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientAdminRead(IReadMessage incMsg)
|
public void ClientAdminRead(IReadMessage incMsg, NetFlags requiredFlags)
|
||||||
{
|
{
|
||||||
|
if (!requiredFlags.HasFlag(NetFlags.Properties)) { return; }
|
||||||
int count = incMsg.ReadUInt16();
|
int count = incMsg.ReadUInt16();
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
@@ -128,8 +129,18 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
cachedServerListInfo = null;
|
cachedServerListInfo = null;
|
||||||
|
|
||||||
ServerName = incMsg.ReadString();
|
NetFlags requiredFlags = (NetFlags)incMsg.ReadByte();
|
||||||
ServerMessageText = incMsg.ReadString();
|
|
||||||
|
if (requiredFlags.HasFlag(NetFlags.Name))
|
||||||
|
{
|
||||||
|
ServerName = incMsg.ReadString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requiredFlags.HasFlag(NetFlags.Message))
|
||||||
|
{
|
||||||
|
ServerMessageText = incMsg.ReadString();
|
||||||
|
}
|
||||||
|
PlayStyle = (PlayStyle)incMsg.ReadByte();
|
||||||
MaxPlayers = incMsg.ReadByte();
|
MaxPlayers = incMsg.ReadByte();
|
||||||
HasPassword = incMsg.ReadBoolean();
|
HasPassword = incMsg.ReadBoolean();
|
||||||
IsPublic = incMsg.ReadBoolean();
|
IsPublic = incMsg.ReadBoolean();
|
||||||
@@ -139,23 +150,23 @@ namespace Barotrauma.Networking
|
|||||||
TickRate = incMsg.ReadRangedInteger(1, 60);
|
TickRate = incMsg.ReadRangedInteger(1, 60);
|
||||||
GameMain.NetworkMember.TickRate = TickRate;
|
GameMain.NetworkMember.TickRate = TickRate;
|
||||||
|
|
||||||
ReadExtraCargo(incMsg);
|
if (requiredFlags.HasFlag(NetFlags.Properties))
|
||||||
|
{
|
||||||
|
ReadExtraCargo(incMsg);
|
||||||
|
}
|
||||||
|
|
||||||
ReadHiddenSubs(incMsg);
|
ReadHiddenSubs(incMsg);
|
||||||
|
|
||||||
GameMain.NetLobbyScreen.UpdateSubVisibility();
|
GameMain.NetLobbyScreen.UpdateSubVisibility();
|
||||||
|
|
||||||
Voting.ClientRead(incMsg);
|
|
||||||
|
|
||||||
bool isAdmin = incMsg.ReadBoolean();
|
bool isAdmin = incMsg.ReadBoolean();
|
||||||
incMsg.ReadPadBits();
|
incMsg.ReadPadBits();
|
||||||
if (isAdmin)
|
if (isAdmin)
|
||||||
{
|
{
|
||||||
ClientAdminRead(incMsg);
|
ClientAdminRead(incMsg, requiredFlags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientAdminWrite(NetFlags dataToSend, int? missionTypeOr = null, int? missionTypeAnd = null, float? levelDifficulty = null, bool? autoRestart = null, int traitorSetting = 0, int botCount = 0, int botSpawnMode = 0, bool? radiationEnabled = null, bool? useRespawnShuttle = null, int maxMissionCount = 0)
|
public void ClientAdminWrite(NetFlags dataToSend, int? missionTypeOr = null, int? missionTypeAnd = null, float? levelDifficulty = null, bool? autoRestart = null, int traitorSetting = 0, int botCount = 0, int botSpawnMode = 0, bool? useRespawnShuttle = null)
|
||||||
{
|
{
|
||||||
if (!GameMain.Client.HasPermission(Networking.ClientPermissions.ManageSettings)) return;
|
if (!GameMain.Client.HasPermission(Networking.ClientPermissions.ManageSettings)) return;
|
||||||
|
|
||||||
@@ -225,8 +236,6 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
outMsg.Write(autoRestart != null);
|
outMsg.Write(autoRestart != null);
|
||||||
outMsg.Write(autoRestart ?? false);
|
outMsg.Write(autoRestart ?? false);
|
||||||
outMsg.Write(radiationEnabled ?? RadiationEnabled);
|
|
||||||
outMsg.Write((byte)maxMissionCount + 1);
|
|
||||||
|
|
||||||
outMsg.WritePadBits();
|
outMsg.WritePadBits();
|
||||||
}
|
}
|
||||||
@@ -711,7 +720,6 @@ namespace Barotrauma.Networking
|
|||||||
RelativeSpacing = 0.05f
|
RelativeSpacing = 0.05f
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
if (ip.InventoryIcon != null || ip.sprite != null)
|
if (ip.InventoryIcon != null || ip.sprite != null)
|
||||||
{
|
{
|
||||||
GUIImage img = new GUIImage(new RectTransform(new Point(itemFrame.Rect.Height), itemFrame.RectTransform),
|
GUIImage img = new GUIImage(new RectTransform(new Point(itemFrame.Rect.Height), itemFrame.RectTransform),
|
||||||
@@ -734,7 +742,7 @@ namespace Barotrauma.Networking
|
|||||||
GUINumberInput.NumberType.Int, textAlignment: Alignment.CenterLeft)
|
GUINumberInput.NumberType.Int, textAlignment: Alignment.CenterLeft)
|
||||||
{
|
{
|
||||||
MinValueInt = 0,
|
MinValueInt = 0,
|
||||||
MaxValueInt = 100,
|
MaxValueInt = MaxExtraCargoItemsOfType,
|
||||||
IntValue = cargoVal
|
IntValue = cargoVal
|
||||||
};
|
};
|
||||||
amountInput.OnValueChanged += (numberInput) =>
|
amountInput.OnValueChanged += (numberInput) =>
|
||||||
@@ -742,16 +750,26 @@ namespace Barotrauma.Networking
|
|||||||
if (ExtraCargo.ContainsKey(ip))
|
if (ExtraCargo.ContainsKey(ip))
|
||||||
{
|
{
|
||||||
ExtraCargo[ip] = numberInput.IntValue;
|
ExtraCargo[ip] = numberInput.IntValue;
|
||||||
if (numberInput.IntValue <= 0) ExtraCargo.Remove(ip);
|
if (numberInput.IntValue <= 0) { ExtraCargo.Remove(ip); }
|
||||||
}
|
}
|
||||||
else
|
else if (ExtraCargo.Keys.Count() < MaxExtraCargoItemTypes)
|
||||||
{
|
{
|
||||||
ExtraCargo.Add(ip, numberInput.IntValue);
|
ExtraCargo.Add(ip, numberInput.IntValue);
|
||||||
}
|
}
|
||||||
|
numberInput.IntValue = ExtraCargo.ContainsKey(ip) ? ExtraCargo[ip] : 0;
|
||||||
|
CoroutineManager.Invoke(() =>
|
||||||
|
{
|
||||||
|
foreach (var child in cargoFrame.Content.GetAllChildren())
|
||||||
|
{
|
||||||
|
if (child.GetChild<GUINumberInput>() is GUINumberInput otherNumberInput)
|
||||||
|
{
|
||||||
|
otherNumberInput.PlusButton.Enabled = ExtraCargo.Keys.Count() < MaxExtraCargoItemTypes && otherNumberInput.IntValue < otherNumberInput.MaxValueInt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 0.0f);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
// antigriefing
|
// antigriefing
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
@@ -913,6 +931,7 @@ namespace Barotrauma.Networking
|
|||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
Whitelist.CreateWhiteListFrame(settingsTabs[(int)SettingsTab.Whitelist]);
|
Whitelist.CreateWhiteListFrame(settingsTabs[(int)SettingsTab.Whitelist]);
|
||||||
|
Whitelist.localEnabled = Whitelist.Enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateLabeledSlider(GUIComponent parent, string labelTag, out GUIScrollBar slider, out GUITextBlock label)
|
private void CreateLabeledSlider(GUIComponent parent, string labelTag, out GUIScrollBar slider, out GUITextBlock label)
|
||||||
|
|||||||
@@ -147,7 +147,14 @@ namespace Barotrauma.Steam
|
|||||||
|
|
||||||
if (currentLobby == null)
|
if (currentLobby == null)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Failed to create Steam lobby");
|
DebugConsole.ThrowError("Failed to create Steam lobby: returned lobby was null");
|
||||||
|
lobbyState = LobbyState.NotConnected;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentLobby.Value.Result != Steamworks.Result.OK)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError($"Failed to create Steam lobby: result was {currentLobby.Value.Result}");
|
||||||
lobbyState = LobbyState.NotConnected;
|
lobbyState = LobbyState.NotConnected;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -525,18 +532,6 @@ namespace Barotrauma.Steam
|
|||||||
}
|
}
|
||||||
|
|
||||||
#region Connecting to servers
|
#region Connecting to servers
|
||||||
private static Steamworks.AuthTicket currentTicket = null;
|
|
||||||
public static Steamworks.AuthTicket GetAuthSessionTicket()
|
|
||||||
{
|
|
||||||
if (!isInitialized)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
currentTicket?.Cancel();
|
|
||||||
currentTicket = Steamworks.SteamUser.GetAuthSessionTicket();
|
|
||||||
return currentTicket;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Steamworks.BeginAuthResult StartAuthSession(byte[] authTicketData, ulong clientSteamID)
|
public static Steamworks.BeginAuthResult StartAuthSession(byte[] authTicketData, ulong clientSteamID)
|
||||||
{
|
{
|
||||||
@@ -884,9 +879,9 @@ namespace Barotrauma.Steam
|
|||||||
|
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
string errorMsg = "Failed to save workshop item preview image to \"" + previewImagePath + "\" when creating workshop item staging folder.";
|
string errorMsg = "Failed to save workshop item preview image when creating workshop item staging folder.";
|
||||||
GameAnalyticsManager.AddErrorEventOnce("SteamManager.CreateWorkshopItemStaging:WriteAllBytesFailed" + previewImagePath,
|
GameAnalyticsManager.AddErrorEventOnce("SteamManager.CreateWorkshopItemStaging:WriteAllBytesFailed" + previewImagePath,
|
||||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg + "\n" + e.Message);
|
GameAnalyticsManager.ErrorSeverity.Error, errorMsg + "\n" + e.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -1434,8 +1429,8 @@ namespace Barotrauma.Steam
|
|||||||
"\" not found. Could not combine path (" + (item.Directory ?? "directory name empty") + ").";
|
"\" not found. Could not combine path (" + (item.Directory ?? "directory name empty") + ").";
|
||||||
DebugConsole.ThrowError(errorMessage);
|
DebugConsole.ThrowError(errorMessage);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("SteamManager.CheckWorkshopItemInstalled:PathCombineException" + item.Title,
|
GameAnalyticsManager.AddErrorEventOnce("SteamManager.CheckWorkshopItemInstalled:PathCombineException" + item.Title,
|
||||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
GameAnalyticsManager.ErrorSeverity.Error,
|
||||||
errorMessage);
|
"Metadata file for a Workshop item not found. Could not combine path.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1567,8 +1562,8 @@ namespace Barotrauma.Steam
|
|||||||
}
|
}
|
||||||
GameAnalyticsManager.AddErrorEventOnce(
|
GameAnalyticsManager.AddErrorEventOnce(
|
||||||
"SteamManager.AutoUpdateWorkshopItems:" + e.Message,
|
"SteamManager.AutoUpdateWorkshopItems:" + e.Message,
|
||||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
GameAnalyticsManager.ErrorSeverity.Error,
|
||||||
"Failed to autoupdate workshop item \"" + item.Title + "\". " + e.Message + "\n" + e.StackTrace.CleanupStackTrace());
|
"Failed to autoupdate workshop item. " + e.Message + "\n" + e.StackTrace.CleanupStackTrace());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ namespace Barotrauma.Networking
|
|||||||
UserData = "capturedevicenotfound"
|
UserData = "capturedevicenotfound"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
GameAnalyticsManager.AddErrorEventOnce("Alc.CaptureDeviceOpenFailed", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
GameAnalyticsManager.AddErrorEventOnce("Alc.CaptureDeviceOpenFailed", GameAnalyticsManager.ErrorSeverity.Error,
|
||||||
"Alc.CaptureDeviceOpen(" + deviceName + ") failed. Error code: " + errorCode);
|
"Alc.CaptureDeviceOpen(" + deviceName + ") failed. Error code: " + errorCode);
|
||||||
GameMain.Config.VoiceSetting = GameSettings.VoiceMode.Disabled;
|
GameMain.Config.VoiceSetting = GameSettings.VoiceMode.Disabled;
|
||||||
Instance?.Dispose();
|
Instance?.Dispose();
|
||||||
|
|||||||
@@ -56,17 +56,12 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
nameBox.Enabled = box.Selected;
|
nameBox.Enabled = box.Selected;
|
||||||
ipBox.Enabled = box.Selected;
|
ipBox.Enabled = box.Selected;
|
||||||
addNewButton.Enabled = box.Selected;
|
addNewButton.Enabled = box.Selected && !string.IsNullOrEmpty(ipBox.Text) && !string.IsNullOrEmpty(nameBox.Text);
|
||||||
|
|
||||||
localEnabled = box.Selected;
|
localEnabled = box.Selected;
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
localEnabled = Enabled;
|
|
||||||
|
|
||||||
var listBox = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.7f), whitelistFrame.RectTransform));
|
var listBox = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.7f), whitelistFrame.RectTransform));
|
||||||
foreach (WhiteListedPlayer wlp in whitelistedPlayers)
|
foreach (WhiteListedPlayer wlp in whitelistedPlayers)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ namespace Barotrauma.Particles
|
|||||||
Prefab = prefab;
|
Prefab = prefab;
|
||||||
}
|
}
|
||||||
|
|
||||||
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, bool mirrorAngle = false, Tuple<Vector2, Vector2> tracerPoints = null)
|
||||||
{
|
{
|
||||||
if (GameMain.Client?.MidRoundSyncing ?? false) { return; }
|
if (GameMain.Client?.MidRoundSyncing ?? false) { return; }
|
||||||
|
|
||||||
@@ -159,7 +159,7 @@ namespace Barotrauma.Particles
|
|||||||
for (float z = 0.0f; z < dist; z += Prefab.Properties.EmitAcrossRayInterval)
|
for (float z = 0.0f; z < dist; z += Prefab.Properties.EmitAcrossRayInterval)
|
||||||
{
|
{
|
||||||
Vector2 pos = tracerPoints.Item1 + dir * z;
|
Vector2 pos = tracerPoints.Item1 + dir * z;
|
||||||
Emit(pos, hullGuess, angle, particleRotation, velocityMultiplier, sizeMultiplier, colorMultiplier, overrideParticle, tracerPoints: null);
|
Emit(pos, hullGuess, angle, particleRotation, velocityMultiplier, sizeMultiplier, colorMultiplier, overrideParticle, mirrorAngle, tracerPoints: null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -169,7 +169,7 @@ namespace Barotrauma.Particles
|
|||||||
float emitInterval = 1.0f / Prefab.Properties.ParticlesPerSecond;
|
float emitInterval = 1.0f / Prefab.Properties.ParticlesPerSecond;
|
||||||
while (emitTimer > emitInterval)
|
while (emitTimer > emitInterval)
|
||||||
{
|
{
|
||||||
Emit(position, hullGuess, angle, particleRotation, velocityMultiplier, sizeMultiplier, colorMultiplier, overrideParticle, tracerPoints: tracerPoints);
|
Emit(position, hullGuess, angle, particleRotation, velocityMultiplier, sizeMultiplier, colorMultiplier, overrideParticle, mirrorAngle, tracerPoints: tracerPoints);
|
||||||
emitTimer -= emitInterval;
|
emitTimer -= emitInterval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -183,7 +183,7 @@ namespace Barotrauma.Particles
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Emit(Vector2 position, Hull hullGuess, float angle, float particleRotation, float velocityMultiplier, float sizeMultiplier, Color? colorMultiplier = null, ParticlePrefab overrideParticle = null, Tuple<Vector2, Vector2> tracerPoints = null)
|
private void Emit(Vector2 position, Hull hullGuess, float angle, float particleRotation, float velocityMultiplier, float sizeMultiplier, Color? colorMultiplier = null, ParticlePrefab overrideParticle = null, bool mirrorAngle = false, Tuple<Vector2, Vector2> tracerPoints = null)
|
||||||
{
|
{
|
||||||
var particlePrefab = overrideParticle ?? Prefab.ParticlePrefab;
|
var particlePrefab = overrideParticle ?? Prefab.ParticlePrefab;
|
||||||
if (particlePrefab == null) { return; }
|
if (particlePrefab == null) { return; }
|
||||||
@@ -191,7 +191,7 @@ namespace Barotrauma.Particles
|
|||||||
Vector2 velocity = Vector2.Zero;
|
Vector2 velocity = Vector2.Zero;
|
||||||
if (!MathUtils.NearlyEqual(Prefab.Properties.VelocityMax * velocityMultiplier, 0.0f) || !MathUtils.NearlyEqual(Prefab.Properties.DistanceMax, 0.0f))
|
if (!MathUtils.NearlyEqual(Prefab.Properties.VelocityMax * velocityMultiplier, 0.0f) || !MathUtils.NearlyEqual(Prefab.Properties.DistanceMax, 0.0f))
|
||||||
{
|
{
|
||||||
angle += Rand.Range(Prefab.Properties.AngleMinRad, Prefab.Properties.AngleMaxRad);
|
angle += Rand.Range(Prefab.Properties.AngleMinRad, Prefab.Properties.AngleMaxRad) * (mirrorAngle ? -1 : 1);
|
||||||
Vector2 dir = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle));
|
Vector2 dir = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle));
|
||||||
velocity = dir * Rand.Range(Prefab.Properties.VelocityMin, Prefab.Properties.VelocityMax) * velocityMultiplier;
|
velocity = dir * Rand.Range(Prefab.Properties.VelocityMin, Prefab.Properties.VelocityMax) * velocityMultiplier;
|
||||||
position += dir * Rand.Range(Prefab.Properties.DistanceMin, Prefab.Properties.DistanceMax);
|
position += dir * Rand.Range(Prefab.Properties.DistanceMin, Prefab.Properties.DistanceMax);
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ namespace Barotrauma
|
|||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg);
|
||||||
#endif
|
#endif
|
||||||
GameAnalyticsManager.AddErrorEventOnce("PhysicsBody.ClientRead:InvalidData" + parentDebugName,
|
GameAnalyticsManager.AddErrorEventOnce("PhysicsBody.ClientRead:InvalidData" + parentDebugName,
|
||||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
GameAnalyticsManager.ErrorSeverity.Error,
|
||||||
errorMsg);
|
errorMsg);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
#region Using Statements
|
#region Using Statements
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using Barotrauma.IO;
|
using Barotrauma.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using GameAnalyticsSDK.Net;
|
|
||||||
using Barotrauma.Steam;
|
using Barotrauma.Steam;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
@@ -245,6 +243,13 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GameAnalyticsManager.SendUserStatistics)
|
||||||
|
{
|
||||||
|
//send crash report before appending debug console messages (which may contain non-anonymous information)
|
||||||
|
GameAnalyticsManager.AddErrorEvent(GameAnalyticsManager.ErrorSeverity.Critical, sb.ToString());
|
||||||
|
GameAnalyticsManager.ShutDown();
|
||||||
|
}
|
||||||
|
|
||||||
sb.AppendLine("Last debug messages:");
|
sb.AppendLine("Last debug messages:");
|
||||||
for (int i = DebugConsole.Messages.Count - 1; i >= 0; i--)
|
for (int i = DebugConsole.Messages.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
@@ -257,11 +262,9 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (GameSettings.SaveDebugConsoleLogs || GameSettings.VerboseLogging) { DebugConsole.SaveLogs(); }
|
if (GameSettings.SaveDebugConsoleLogs || GameSettings.VerboseLogging) { DebugConsole.SaveLogs(); }
|
||||||
|
|
||||||
if (GameSettings.SendUserStatistics)
|
if (GameAnalyticsManager.SendUserStatistics)
|
||||||
{
|
{
|
||||||
CrashMessageBox("A crash report (\"" + filePath + "\") was saved in the root folder of the game and sent to the developers.", filePath);
|
CrashMessageBox("A crash report (\"" + filePath + "\") was saved in the root folder of the game and sent to the developers.", filePath);
|
||||||
GameAnalytics.AddErrorEvent(EGAErrorSeverity.Critical, crashReport);
|
|
||||||
GameAnalytics.OnQuit();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,14 +7,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
protected readonly GUIComponent newGameContainer, loadGameContainer;
|
protected readonly GUIComponent newGameContainer, loadGameContainer;
|
||||||
|
|
||||||
protected GUIListBox subList;
|
|
||||||
protected GUIListBox saveList;
|
protected GUIListBox saveList;
|
||||||
protected List<GUITickBox> subTickBoxes;
|
|
||||||
|
|
||||||
protected GUITextBox saveNameBox, seedBox;
|
protected GUITextBox saveNameBox, seedBox;
|
||||||
|
|
||||||
protected GUILayoutGroup subPreviewContainer;
|
|
||||||
|
|
||||||
protected GUIButton loadGameButton;
|
protected GUIButton loadGameButton;
|
||||||
|
|
||||||
public Action<SubmarineInfo, string, string, CampaignSettings> StartNewGame;
|
public Action<SubmarineInfo, string, string, CampaignSettings> StartNewGame;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using System.Linq;
|
|||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using Barotrauma.Extensions;
|
using Barotrauma.Extensions;
|
||||||
|
using Barotrauma.Networking;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -14,55 +15,79 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
private GUIButton deleteMpSaveButton;
|
private GUIButton deleteMpSaveButton;
|
||||||
|
|
||||||
public MultiPlayerCampaignSetupUI(GUIComponent newGameContainer, GUIComponent loadGameContainer, IEnumerable<SubmarineInfo> submarines, IEnumerable<string> saveFiles = null)
|
public MultiPlayerCampaignSetupUI(GUIComponent newGameContainer, GUIComponent loadGameContainer, IEnumerable<string> saveFiles = null)
|
||||||
: base(newGameContainer, loadGameContainer)
|
: base(newGameContainer, loadGameContainer)
|
||||||
{
|
{
|
||||||
var columnContainer = new GUILayoutGroup(new RectTransform(Vector2.One, newGameContainer.RectTransform), isHorizontal: true)
|
var verticalLayout = new GUILayoutGroup(new RectTransform(Vector2.One, newGameContainer.RectTransform), isHorizontal: false)
|
||||||
{
|
{
|
||||||
Stretch = true,
|
Stretch = true,
|
||||||
RelativeSpacing = 0.0f
|
RelativeSpacing = 0.0f
|
||||||
};
|
};
|
||||||
|
|
||||||
var leftColumn = new GUILayoutGroup(new RectTransform(Vector2.One, columnContainer.RectTransform))
|
// New game
|
||||||
{
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.03f), verticalLayout.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("SaveName"), font: GUI.SubHeadingFont, textAlignment: Alignment.BottomLeft);
|
||||||
Stretch = true,
|
saveNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.03f), verticalLayout.RectTransform) { MinSize = new Point(0, 20) }, string.Empty)
|
||||||
RelativeSpacing = 0.015f
|
|
||||||
};
|
|
||||||
|
|
||||||
var rightColumn = new GUILayoutGroup(new RectTransform(Vector2.Zero, columnContainer.RectTransform))
|
|
||||||
{
|
|
||||||
Stretch = true,
|
|
||||||
RelativeSpacing = 0.015f
|
|
||||||
};
|
|
||||||
|
|
||||||
columnContainer.Recalculate();
|
|
||||||
|
|
||||||
// New game left side
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.02f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("SaveName"), font: GUI.SubHeadingFont);
|
|
||||||
saveNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, string.Empty)
|
|
||||||
{
|
{
|
||||||
textFilterFunction = (string str) => { return ToolBox.RemoveInvalidFileNameChars(str); }
|
textFilterFunction = (string str) => { return ToolBox.RemoveInvalidFileNameChars(str); }
|
||||||
};
|
};
|
||||||
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.02f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("MapSeed"), font: GUI.SubHeadingFont);
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.03f), verticalLayout.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("MapSeed"), font: GUI.SubHeadingFont, textAlignment: Alignment.BottomLeft);
|
||||||
seedBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, ToolBox.RandomSeed(8));
|
seedBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.03f), verticalLayout.RectTransform) { MinSize = new Point(0, 20) }, ToolBox.RandomSeed(8));
|
||||||
|
|
||||||
// Spacing to fix the multiplayer campaign setup layout
|
GUIFrame radiationBoxContainer
|
||||||
CreateMultiplayerCampaignSubList(leftColumn.RectTransform);
|
= new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), verticalLayout.RectTransform), style: null);
|
||||||
|
GUITickBox radiationEnabledTickBox = null;
|
||||||
//spacing
|
if (MapGenerationParams.Instance.RadiationParams != null)
|
||||||
//new GUIFrame(new RectTransform(new Vector2(1.0f, 0.25f), leftColumn.RectTransform), style: null);
|
|
||||||
|
|
||||||
// New game right side
|
|
||||||
subPreviewContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), rightColumn.RectTransform))
|
|
||||||
{
|
{
|
||||||
Stretch = true
|
radiationEnabledTickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.5f), radiationBoxContainer.RectTransform, Anchor.Center), TextManager.Get("CampaignOption.EnableRadiation"), font: GUI.Style.Font)
|
||||||
|
{
|
||||||
|
Selected = true,
|
||||||
|
OnSelected = box => true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var maxMissionCountSettingHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), verticalLayout.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) { Stretch = true };
|
||||||
|
var maxMissionCountDescription = new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.0f), maxMissionCountSettingHolder.RectTransform), TextManager.Get("maxmissioncount", fallBackTag: "missions"), wrap: true)
|
||||||
|
{
|
||||||
|
ToolTip = TextManager.Get("maxmissioncounttooltip")
|
||||||
};
|
};
|
||||||
|
int maxMissionCount = GameMain.NetworkMember.ServerSettings.MaxMissionCount;
|
||||||
|
var maxMissionCountContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), maxMissionCountSettingHolder.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) { RelativeSpacing = 0.05f, Stretch = true };
|
||||||
|
var maxMissionCountButtons = new GUIButton[2];
|
||||||
|
maxMissionCountButtons[0]
|
||||||
|
= new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), maxMissionCountContainer.RectTransform),
|
||||||
|
style: "GUIButtonToggleLeft");
|
||||||
|
var maxMissionCountText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), maxMissionCountContainer.RectTransform), "0", textAlignment: Alignment.Center, style: "GUITextBox");
|
||||||
|
|
||||||
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.12f),
|
void updateMissionCountText()
|
||||||
leftColumn.RectTransform) { MaxSize = new Point(int.MaxValue, 60) }, childAnchor: Anchor.BottomRight, isHorizontal: true);
|
{
|
||||||
|
maxMissionCount = MathHelper.Clamp(maxMissionCount,
|
||||||
|
CampaignSettings.MinMissionCountLimit,
|
||||||
|
CampaignSettings.MaxMissionCountLimit);
|
||||||
|
maxMissionCountText.Text = maxMissionCount.ToString(CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
maxMissionCountButtons[1]
|
||||||
|
= new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), maxMissionCountContainer.RectTransform),
|
||||||
|
style: "GUIButtonToggleRight");
|
||||||
|
maxMissionCountButtons[0].OnClicked = (button, o) =>
|
||||||
|
{
|
||||||
|
maxMissionCount--;
|
||||||
|
updateMissionCountText();
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
maxMissionCountButtons[1].OnClicked = (button, o) =>
|
||||||
|
{
|
||||||
|
maxMissionCount++;
|
||||||
|
updateMissionCountText();
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
updateMissionCountText();
|
||||||
|
maxMissionCountSettingHolder.Children.ForEach(c => c.ToolTip = maxMissionCountSettingHolder.ToolTip);
|
||||||
|
|
||||||
StartButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1f), buttonContainer.RectTransform, Anchor.BottomRight) { MaxSize = new Point(350, 60) }, TextManager.Get("StartCampaignButton"))
|
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.04f),
|
||||||
|
verticalLayout.RectTransform) { MaxSize = new Point(int.MaxValue, 60) }, childAnchor: Anchor.BottomRight, isHorizontal: true);
|
||||||
|
|
||||||
|
StartButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1f), buttonContainer.RectTransform, Anchor.BottomRight), TextManager.Get("StartCampaignButton"))
|
||||||
{
|
{
|
||||||
OnClicked = (GUIButton btn, object userData) =>
|
OnClicked = (GUIButton btn, object userData) =>
|
||||||
{
|
{
|
||||||
@@ -85,20 +110,19 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (string.IsNullOrEmpty(selectedSub.MD5Hash.Hash))
|
if (string.IsNullOrEmpty(selectedSub.MD5Hash.Hash))
|
||||||
{
|
{
|
||||||
((GUITextBlock)subList.SelectedComponent).TextColor = Color.DarkRed * 0.8f;
|
new GUIMessageBox(TextManager.Get("error"), TextManager.Get("nohashsubmarineselected"));
|
||||||
subList.SelectedComponent.CanBeFocused = false;
|
|
||||||
subList.Deselect();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
string savePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Multiplayer, saveNameBox.Text);
|
string savePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Multiplayer, saveNameBox.Text);
|
||||||
bool hasRequiredContentPackages = selectedSub.RequiredContentPackagesInstalled;
|
bool hasRequiredContentPackages = selectedSub.RequiredContentPackagesInstalled;
|
||||||
|
|
||||||
CampaignSettings settings = new CampaignSettings();
|
CampaignSettings settings = new CampaignSettings
|
||||||
|
{
|
||||||
|
RadiationEnabled = radiationEnabledTickBox?.Selected ?? GameMain.NetworkMember.ServerSettings.RadiationEnabled,
|
||||||
|
MaxMissionCount = maxMissionCount
|
||||||
|
};
|
||||||
|
|
||||||
settings.RadiationEnabled = GameMain.NetLobbyScreen.IsRadiationEnabled();
|
|
||||||
settings.MaxMissionCount = GameMain.NetLobbyScreen.GetMaxMissionCount();
|
|
||||||
|
|
||||||
if (selectedSub.HasTag(SubmarineTag.Shuttle) || !hasRequiredContentPackages)
|
if (selectedSub.HasTag(SubmarineTag.Shuttle) || !hasRequiredContentPackages)
|
||||||
{
|
{
|
||||||
if (!hasRequiredContentPackages)
|
if (!hasRequiredContentPackages)
|
||||||
@@ -148,7 +172,9 @@ namespace Barotrauma
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
StartButton.RectTransform.MaxSize = RectTransform.MaxPoint;
|
||||||
|
StartButton.Children.ForEach(c => c.RectTransform.MaxSize = RectTransform.MaxPoint);
|
||||||
|
|
||||||
InitialMoneyText = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1f), buttonContainer.RectTransform), "", font: GUI.Style.SmallFont, textColor: GUI.Style.Green)
|
InitialMoneyText = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1f), buttonContainer.RectTransform), "", font: GUI.Style.SmallFont, textColor: GUI.Style.Green)
|
||||||
{
|
{
|
||||||
TextGetter = () =>
|
TextGetter = () =>
|
||||||
@@ -163,114 +189,11 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
columnContainer.Recalculate();
|
verticalLayout.Recalculate();
|
||||||
leftColumn.Recalculate();
|
|
||||||
rightColumn.Recalculate();
|
|
||||||
|
|
||||||
if (submarines != null) { UpdateSubList(submarines); }
|
|
||||||
UpdateLoadMenu(saveFiles);
|
UpdateLoadMenu(saveFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateMultiplayerCampaignSubList(RectTransform parent)
|
|
||||||
{
|
|
||||||
GUILayoutGroup subHolder = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.725f), parent))
|
|
||||||
{
|
|
||||||
RelativeSpacing = 0.005f,
|
|
||||||
Stretch = true
|
|
||||||
};
|
|
||||||
|
|
||||||
var subLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.055f), subHolder.RectTransform) { MinSize = new Point(0, 25) }, TextManager.Get("purchasablesubmarines", fallBackTag: "workshoplabelsubmarines"), font: GUI.SubHeadingFont);
|
|
||||||
|
|
||||||
var filterContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), subHolder.RectTransform), isHorizontal: true)
|
|
||||||
{
|
|
||||||
Stretch = true
|
|
||||||
};
|
|
||||||
var searchTitle = new GUITextBlock(new RectTransform(new Vector2(0.001f, 1.0f), filterContainer.RectTransform), TextManager.Get("serverlog.filter"), textAlignment: Alignment.CenterLeft, font: GUI.Font);
|
|
||||||
var searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 1.0f), filterContainer.RectTransform, Anchor.CenterRight), font: GUI.Font, createClearButton: true);
|
|
||||||
filterContainer.RectTransform.MinSize = searchBox.RectTransform.MinSize;
|
|
||||||
searchBox.OnSelected += (sender, userdata) => { searchTitle.Visible = false; };
|
|
||||||
searchBox.OnDeselected += (sender, userdata) => { searchTitle.Visible = true; };
|
|
||||||
searchBox.OnTextChanged += (textBox, text) =>
|
|
||||||
{
|
|
||||||
foreach (GUIComponent child in subList.Content.Children)
|
|
||||||
{
|
|
||||||
if (!(child.UserData is SubmarineInfo sub)) { continue; }
|
|
||||||
child.Visible = string.IsNullOrEmpty(text) ? true : sub.DisplayName.ToLower().Contains(text.ToLower());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
subList = new GUIListBox(new RectTransform(Vector2.One, subHolder.RectTransform));
|
|
||||||
subTickBoxes = new List<GUITickBox>();
|
|
||||||
|
|
||||||
for (int i = 0; i < GameMain.Client.ServerSubmarines.Count; i++)
|
|
||||||
{
|
|
||||||
SubmarineInfo sub = GameMain.Client.ServerSubmarines[i];
|
|
||||||
|
|
||||||
if (!sub.IsCampaignCompatible) continue;
|
|
||||||
|
|
||||||
var frame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), subList.Content.RectTransform) { MinSize = new Point(0, 20) },
|
|
||||||
style: "ListBoxElement")
|
|
||||||
{
|
|
||||||
ToolTip = sub.Description,
|
|
||||||
UserData = sub
|
|
||||||
};
|
|
||||||
|
|
||||||
int buttonSize = (int)(frame.Rect.Height * 0.8f);
|
|
||||||
|
|
||||||
GUITickBox tickBox = new GUITickBox(new RectTransform(new Vector2(0.8f, 1.0f), frame.RectTransform, Anchor.CenterLeft), ToolBox.LimitString(sub.DisplayName, GUI.Font, subList.Content.Rect.Width - 65))
|
|
||||||
{
|
|
||||||
UserData = sub,
|
|
||||||
OnSelected = (GUITickBox box) =>
|
|
||||||
{
|
|
||||||
GameMain.Client.RequestCampaignSub(box.UserData as SubmarineInfo, box.Selected);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
subTickBoxes.Add(tickBox);
|
|
||||||
tickBox.Selected = GameMain.NetLobbyScreen.CampaignSubmarines.Contains(sub);
|
|
||||||
|
|
||||||
frame.RectTransform.MinSize = new Point(0, tickBox.RectTransform.MinSize.Y);
|
|
||||||
|
|
||||||
var subTextBlock = tickBox.TextBlock;
|
|
||||||
|
|
||||||
var matchingSub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == sub.Name && s.MD5Hash?.Hash == sub.MD5Hash?.Hash);
|
|
||||||
if (matchingSub == null) matchingSub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == sub.Name);
|
|
||||||
|
|
||||||
if (matchingSub == null)
|
|
||||||
{
|
|
||||||
subTextBlock.TextColor = new Color(subTextBlock.TextColor, 0.5f);
|
|
||||||
frame.ToolTip = TextManager.Get("SubNotFound");
|
|
||||||
}
|
|
||||||
else if (matchingSub?.MD5Hash == null || matchingSub.MD5Hash?.Hash != sub.MD5Hash?.Hash)
|
|
||||||
{
|
|
||||||
subTextBlock.TextColor = new Color(subTextBlock.TextColor, 0.5f);
|
|
||||||
frame.ToolTip = TextManager.Get("SubDoesntMatch");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sub.RequiredContentPackagesInstalled)
|
|
||||||
{
|
|
||||||
subTextBlock.TextColor = Color.Lerp(subTextBlock.TextColor, Color.DarkRed, 0.5f);
|
|
||||||
frame.ToolTip = TextManager.Get("ContentPackageMismatch") + "\n\n" + frame.RawToolTip;
|
|
||||||
}
|
|
||||||
|
|
||||||
var classText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), frame.RectTransform, Anchor.CenterRight),
|
|
||||||
TextManager.Get($"submarineclass.{sub.SubmarineClass}"), textAlignment: Alignment.CenterRight, font: GUI.SmallFont)
|
|
||||||
{
|
|
||||||
TextColor = subTextBlock.TextColor * 0.8f,
|
|
||||||
ToolTip = subTextBlock.RawToolTip
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RefreshMultiplayerCampaignSubUI(List<SubmarineInfo> campaignSubs)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < subTickBoxes.Count; i++)
|
|
||||||
{
|
|
||||||
subTickBoxes[i].Selected = campaignSubs.Contains(subTickBoxes[i].UserData as SubmarineInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<CoroutineStatus> WaitForCampaignSetup()
|
private IEnumerable<CoroutineStatus> WaitForCampaignSetup()
|
||||||
{
|
{
|
||||||
GUI.SetCursorWaiting();
|
GUI.SetCursorWaiting();
|
||||||
@@ -298,64 +221,6 @@ namespace Barotrauma
|
|||||||
yield return CoroutineStatus.Success;
|
yield return CoroutineStatus.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateSubList(IEnumerable<SubmarineInfo> submarines)
|
|
||||||
{
|
|
||||||
List<SubmarineInfo> subsToShow;
|
|
||||||
string downloadFolder = Path.GetFullPath(SaveUtil.SubmarineDownloadFolder);
|
|
||||||
subsToShow = submarines.Where(s => s.IsCampaignCompatibleIgnoreClass && Path.GetDirectoryName(Path.GetFullPath(s.FilePath)) != downloadFolder).ToList();
|
|
||||||
|
|
||||||
subsToShow.Sort((s1, s2) =>
|
|
||||||
{
|
|
||||||
int p1 = s1.Price > CampaignMode.InitialMoney ? 10 : 0;
|
|
||||||
int p2 = s2.Price > CampaignMode.InitialMoney ? 10 : 0;
|
|
||||||
return p1.CompareTo(p2) * 100 + s1.Name.CompareTo(s2.Name);
|
|
||||||
});
|
|
||||||
|
|
||||||
subList.ClearChildren();
|
|
||||||
|
|
||||||
foreach (SubmarineInfo sub in subsToShow)
|
|
||||||
{
|
|
||||||
var textBlock = new GUITextBlock(
|
|
||||||
new RectTransform(new Vector2(1, 0.1f), subList.Content.RectTransform) { MinSize = new Point(0, 30) },
|
|
||||||
ToolBox.LimitString(sub.DisplayName, GUI.Font, subList.Rect.Width - 65), style: "ListBoxElement")
|
|
||||||
{
|
|
||||||
ToolTip = sub.Description,
|
|
||||||
UserData = sub
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!sub.RequiredContentPackagesInstalled)
|
|
||||||
{
|
|
||||||
textBlock.TextColor = Color.Lerp(textBlock.TextColor, Color.DarkRed, .5f);
|
|
||||||
textBlock.ToolTip = TextManager.Get("ContentPackageMismatch") + "\n\n" + textBlock.RawToolTip;
|
|
||||||
}
|
|
||||||
|
|
||||||
var priceText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), textBlock.RectTransform, Anchor.CenterRight),
|
|
||||||
TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", sub.Price)), textAlignment: Alignment.CenterRight, font: GUI.SmallFont)
|
|
||||||
{
|
|
||||||
TextColor = sub.Price > CampaignMode.InitialMoney ? GUI.Style.Red : textBlock.TextColor * 0.8f,
|
|
||||||
ToolTip = textBlock.ToolTip
|
|
||||||
};
|
|
||||||
#if !DEBUG
|
|
||||||
if (!GameMain.DebugDraw)
|
|
||||||
{
|
|
||||||
if (sub.Price > CampaignMode.InitialMoney || !sub.IsCampaignCompatible)
|
|
||||||
{
|
|
||||||
textBlock.CanBeFocused = false;
|
|
||||||
textBlock.TextColor *= 0.5f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if (SubmarineInfo.SavedSubmarines.Any())
|
|
||||||
{
|
|
||||||
var validSubs = subsToShow.Where(s => s.IsCampaignCompatible && s.Price <= CampaignMode.InitialMoney).ToList();
|
|
||||||
if (validSubs.Count > 0)
|
|
||||||
{
|
|
||||||
subList.Select(validSubs[Rand.Int(validSubs.Count)]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<string> prevSaveFiles;
|
private List<string> prevSaveFiles;
|
||||||
public void UpdateLoadMenu(IEnumerable<string> saveFiles = null)
|
public void UpdateLoadMenu(IEnumerable<string> saveFiles = null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
class SinglePlayerCampaignSetupUI : CampaignSetupUI
|
class SinglePlayerCampaignSetupUI : CampaignSetupUI
|
||||||
{
|
{
|
||||||
|
private GUIListBox subList;
|
||||||
|
|
||||||
|
protected GUILayoutGroup subPreviewContainer;
|
||||||
|
|
||||||
public CharacterInfo.AppearanceCustomizationMenu[] CharacterMenus { get; private set; }
|
public CharacterInfo.AppearanceCustomizationMenu[] CharacterMenus { get; private set; }
|
||||||
|
|
||||||
private GUIButton nextButton;
|
private GUIButton nextButton;
|
||||||
@@ -38,7 +42,7 @@ namespace Barotrauma
|
|||||||
pageContainer.BarScroll = targetScroll;
|
pageContainer.BarScroll = targetScroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0; i<CharacterMenus.Length; i++)
|
for (int i = 0; i < CharacterMenus.Length; i++)
|
||||||
{
|
{
|
||||||
CharacterMenus[i]?.Update();
|
CharacterMenus[i]?.Update();
|
||||||
}
|
}
|
||||||
@@ -77,6 +81,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
ScrollBarEnabled = false,
|
ScrollBarEnabled = false,
|
||||||
ScrollBarVisible = false,
|
ScrollBarVisible = false,
|
||||||
|
AllowArrowKeyScroll = false,
|
||||||
HoverCursor = CursorState.Default
|
HoverCursor = CursorState.Default
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -705,7 +705,7 @@ namespace Barotrauma.CharacterEditor
|
|||||||
{
|
{
|
||||||
string errorMsg = "Attempted to modify the state of the physics simulation while a time step was running.";
|
string errorMsg = "Attempted to modify the state of the physics simulation while a time step was running.";
|
||||||
DebugConsole.ThrowError(errorMsg, e);
|
DebugConsole.ThrowError(errorMsg, e);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("CharacterEditorScreen.Update:WorldLockedException" + e.Message, GameAnalyticsSDK.Net.EGAErrorSeverity.Critical, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("CharacterEditorScreen.Update:WorldLockedException" + e.Message, GameAnalyticsManager.ErrorSeverity.Critical, errorMsg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Camera
|
// Camera
|
||||||
|
|||||||
@@ -732,9 +732,7 @@ namespace Barotrauma
|
|||||||
if (!string.IsNullOrEmpty(subName))
|
if (!string.IsNullOrEmpty(subName))
|
||||||
{
|
{
|
||||||
DebugConsole.NewMessage($"Loading the predefined quick start sub \"{subName}\"", Color.White);
|
DebugConsole.NewMessage($"Loading the predefined quick start sub \"{subName}\"", Color.White);
|
||||||
selectedSub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s =>
|
selectedSub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name.ToLowerInvariant() == subName.ToLowerInvariant());
|
||||||
s.Name.ToLower() == subName.ToLower());
|
|
||||||
|
|
||||||
if (selectedSub == null)
|
if (selectedSub == null)
|
||||||
{
|
{
|
||||||
DebugConsole.NewMessage($"Cannot find a sub that matches the name \"{subName}\".", Color.Red);
|
DebugConsole.NewMessage($"Cannot find a sub that matches the name \"{subName}\".", Color.Red);
|
||||||
@@ -1055,17 +1053,23 @@ namespace Barotrauma
|
|||||||
|
|
||||||
GUI.Draw(Cam, spriteBatch);
|
GUI.Draw(Cam, spriteBatch);
|
||||||
|
|
||||||
#if !UNSTABLE
|
|
||||||
string versionString = "Barotrauma v" + GameMain.Version + " (" + AssemblyInfo.BuildString + ", branch " + AssemblyInfo.GitBranch + ", revision " + AssemblyInfo.GitRevision + ")";
|
|
||||||
GUI.SmallFont.DrawString(spriteBatch, versionString, new Vector2(HUDLayoutSettings.Padding, GameMain.GraphicsHeight - GUI.SmallFont.MeasureString(versionString).Y - HUDLayoutSettings.Padding * 0.75f), Color.White * 0.7f);
|
|
||||||
#endif
|
|
||||||
if (selectedTab != Tab.Credits)
|
if (selectedTab != Tab.Credits)
|
||||||
{
|
{
|
||||||
|
#if !UNSTABLE
|
||||||
|
string versionString = "Barotrauma v" + GameMain.Version + " (" + AssemblyInfo.BuildString + ", branch " + AssemblyInfo.GitBranch + ", revision " + AssemblyInfo.GitRevision + ")";
|
||||||
|
GUI.SmallFont.DrawString(spriteBatch, versionString, new Vector2(HUDLayoutSettings.Padding, GameMain.GraphicsHeight - GUI.SmallFont.MeasureString(versionString).Y - HUDLayoutSettings.Padding * 0.75f), Color.White * 0.7f);
|
||||||
|
#endif
|
||||||
|
string gameAnalyticsStatus = TextManager.Get($"GameAnalyticsStatus.{GameAnalyticsManager.UserConsented}");
|
||||||
|
Vector2 textSize = GUI.SmallFont.MeasureString(gameAnalyticsStatus).ToPoint().ToVector2();
|
||||||
|
GUI.SmallFont.DrawString(spriteBatch, gameAnalyticsStatus, new Vector2(HUDLayoutSettings.Padding, GameMain.GraphicsHeight - GUI.SmallFont.LineHeight * 2 - HUDLayoutSettings.Padding * 0.75f), Color.White * 0.7f);
|
||||||
|
|
||||||
|
|
||||||
Vector2 textPos = new Vector2(GameMain.GraphicsWidth - HUDLayoutSettings.Padding, GameMain.GraphicsHeight - HUDLayoutSettings.Padding * 0.75f);
|
Vector2 textPos = new Vector2(GameMain.GraphicsWidth - HUDLayoutSettings.Padding, GameMain.GraphicsHeight - HUDLayoutSettings.Padding * 0.75f);
|
||||||
for (int i = legalCrap.Length - 1; i >= 0; i--)
|
for (int i = legalCrap.Length - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
Vector2 textSize = GUI.SmallFont.MeasureString(legalCrap[i]);
|
textSize = GUI.SmallFont.MeasureString(legalCrap[i])
|
||||||
textSize = new Vector2((int)textSize.X, (int)textSize.Y);
|
.ToPoint().ToVector2();
|
||||||
bool mouseOn = i == 0 &&
|
bool mouseOn = i == 0 &&
|
||||||
PlayerInput.MousePosition.X > textPos.X - textSize.X && PlayerInput.MousePosition.X < textPos.X &&
|
PlayerInput.MousePosition.X > textPos.X - textSize.X && PlayerInput.MousePosition.X < textPos.X &&
|
||||||
PlayerInput.MousePosition.Y > textPos.Y - textSize.Y && PlayerInput.MousePosition.Y < textPos.Y;
|
PlayerInput.MousePosition.Y > textPos.Y - textSize.Y && PlayerInput.MousePosition.Y < textPos.Y;
|
||||||
@@ -1121,8 +1125,8 @@ namespace Barotrauma
|
|||||||
DebugConsole.ThrowError("Copying the file \"" + selectedSub.FilePath + "\" failed. The file may have been deleted or in use by another process. Try again or select another submarine.", e);
|
DebugConsole.ThrowError("Copying the file \"" + selectedSub.FilePath + "\" failed. The file may have been deleted or in use by another process. Try again or select another submarine.", e);
|
||||||
GameAnalyticsManager.AddErrorEventOnce(
|
GameAnalyticsManager.AddErrorEventOnce(
|
||||||
"MainMenuScreen.StartGame:IOException" + selectedSub.Name,
|
"MainMenuScreen.StartGame:IOException" + selectedSub.Name,
|
||||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
GameAnalyticsManager.ErrorSeverity.Error,
|
||||||
"Copying the file \"" + selectedSub.FilePath + "\" failed.\n" + e.Message + "\n" + Environment.StackTrace.CleanupStackTrace());
|
"Copying a submarine file failed. " + e.Message + "\n" + Environment.StackTrace.CleanupStackTrace());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1446,7 +1450,7 @@ namespace Barotrauma
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
DebugConsole.ThrowError("Fetching remote content to the main menu failed.", e);
|
DebugConsole.ThrowError("Fetching remote content to the main menu failed.", e);
|
||||||
#endif
|
#endif
|
||||||
GameAnalyticsManager.AddErrorEventOnce("MainMenuScreen.FetchRemoteContent:Exception", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
GameAnalyticsManager.AddErrorEventOnce("MainMenuScreen.FetchRemoteContent:Exception", GameAnalyticsManager.ErrorSeverity.Error,
|
||||||
"Fetching remote content to the main menu failed. " + e.Message);
|
"Fetching remote content to the main menu failed. " + e.Message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1489,7 +1493,7 @@ namespace Barotrauma
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
DebugConsole.ThrowError("Reading received remote main menu content failed.", e);
|
DebugConsole.ThrowError("Reading received remote main menu content failed.", e);
|
||||||
#endif
|
#endif
|
||||||
GameAnalyticsManager.AddErrorEventOnce("MainMenuScreen.WairForRemoteContentReceived:Exception", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
GameAnalyticsManager.AddErrorEventOnce("MainMenuScreen.WairForRemoteContentReceived:Exception", GameAnalyticsManager.ErrorSeverity.Error,
|
||||||
"Reading received remote main menu content failed. " + e.Message);
|
"Reading received remote main menu content failed. " + e.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using System.Collections.Generic;
|
|||||||
using Barotrauma.IO;
|
using Barotrauma.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
using Barotrauma.Steam;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -40,12 +41,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private readonly GUIScrollBar levelDifficultyScrollBar;
|
private readonly GUIScrollBar levelDifficultyScrollBar;
|
||||||
|
|
||||||
private readonly GUITickBox radiationEnabledTickBox;
|
|
||||||
|
|
||||||
private readonly GUIButton[] maxMissionCountButtons;
|
|
||||||
private readonly GUITextBlock maxMissionCountText;
|
|
||||||
private readonly GUITextBlock maxMissionCountDescription;
|
|
||||||
|
|
||||||
private readonly GUIButton[] traitorProbabilityButtons;
|
private readonly GUIButton[] traitorProbabilityButtons;
|
||||||
private readonly GUITextBlock traitorProbabilityText;
|
private readonly GUITextBlock traitorProbabilityText;
|
||||||
|
|
||||||
@@ -192,6 +187,9 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IReadOnlyList<SubmarineInfo> GetSubList()
|
||||||
|
=> SubList.Content.Children.Select(c => c.UserData as SubmarineInfo).ToArray();
|
||||||
|
|
||||||
public readonly GUIListBox PlayerList;
|
public readonly GUIListBox PlayerList;
|
||||||
|
|
||||||
public GUITextBox CharacterNameBox
|
public GUITextBox CharacterNameBox
|
||||||
@@ -1185,45 +1183,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (MapGenerationParams.Instance.RadiationParams != null)
|
|
||||||
{
|
|
||||||
radiationEnabledTickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), settingsContent.RectTransform), TextManager.Get("CampaignOption.EnableRadiation"), font: GUI.Style.Font)
|
|
||||||
{
|
|
||||||
Selected = true,
|
|
||||||
OnSelected = box =>
|
|
||||||
{
|
|
||||||
GameMain.Client.ServerSettings.ClientAdminWrite(ServerSettings.NetFlags.Misc, radiationEnabled: box.Selected);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var maxMissionCountSettingHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), settingsContent.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) { Stretch = true };
|
|
||||||
maxMissionCountDescription = new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.0f), maxMissionCountSettingHolder.RectTransform), TextManager.Get("maxmissioncount", fallBackTag: "missions"), wrap: true)
|
|
||||||
{
|
|
||||||
ToolTip = TextManager.Get("maxmissioncounttooltip")
|
|
||||||
};
|
|
||||||
var maxMissionCountContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), maxMissionCountSettingHolder.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) { RelativeSpacing = 0.05f, Stretch = true };
|
|
||||||
maxMissionCountButtons = new GUIButton[2];
|
|
||||||
maxMissionCountButtons[0] = new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), maxMissionCountContainer.RectTransform), style: "GUIButtonToggleLeft")
|
|
||||||
{
|
|
||||||
OnClicked = (button, obj) =>
|
|
||||||
{
|
|
||||||
GameMain.Client.ServerSettings.ClientAdminWrite(ServerSettings.NetFlags.Misc, maxMissionCount: -1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
maxMissionCountText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), maxMissionCountContainer.RectTransform), "0", textAlignment: Alignment.Center, style: "GUITextBox");
|
|
||||||
maxMissionCountButtons[1] = new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), maxMissionCountContainer.RectTransform), style: "GUIButtonToggleRight")
|
|
||||||
{
|
|
||||||
OnClicked = (button, obj) =>
|
|
||||||
{
|
|
||||||
GameMain.Client.ServerSettings.ClientAdminWrite(ServerSettings.NetFlags.Misc, maxMissionCount: 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
maxMissionCountSettingHolder.Children.ForEach(c => c.ToolTip = maxMissionCountSettingHolder.ToolTip);
|
|
||||||
|
|
||||||
List<GUIComponent> settingsElements = settingsContent.Children.ToList();
|
List<GUIComponent> settingsElements = settingsContent.Children.ToList();
|
||||||
for (int i = 0; i < settingsElements.Count; i++)
|
for (int i = 0; i < settingsElements.Count; i++)
|
||||||
{
|
{
|
||||||
@@ -1372,16 +1331,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
SeedBox.Enabled = !CampaignFrame.Visible && !CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
|
SeedBox.Enabled = !CampaignFrame.Visible && !CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
|
||||||
levelDifficultyScrollBar.Enabled = !CampaignFrame.Visible && !CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
|
levelDifficultyScrollBar.Enabled = !CampaignFrame.Visible && !CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
|
||||||
if (radiationEnabledTickBox != null)
|
|
||||||
{
|
|
||||||
radiationEnabledTickBox.Enabled = CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
|
|
||||||
}
|
|
||||||
maxMissionCountDescription.Enabled = CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
|
|
||||||
maxMissionCountText.Enabled = CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
|
|
||||||
foreach (var button in maxMissionCountButtons)
|
|
||||||
{
|
|
||||||
button.Enabled = CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
|
|
||||||
}
|
|
||||||
|
|
||||||
traitorProbabilityButtons[0].Enabled = traitorProbabilityButtons[1].Enabled = traitorProbabilityText.Enabled =
|
traitorProbabilityButtons[0].Enabled = traitorProbabilityButtons[1].Enabled = traitorProbabilityText.Enabled =
|
||||||
!CampaignFrame.Visible && !CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
|
!CampaignFrame.Visible && !CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
|
||||||
@@ -2163,17 +2112,126 @@ namespace Barotrauma
|
|||||||
if (child != null) { PlayerList.RemoveChild(child); }
|
if (child != null) { PlayerList.RemoveChild(child); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Client ExtractClientFromClickableArea(GUITextBlock.ClickableArea area)
|
||||||
|
{
|
||||||
|
if (!UInt64.TryParse(area.Data.Metadata, out UInt64 id)) { return null; }
|
||||||
|
Client client = GameMain.Client.ConnectedClients.Find(c => c.SteamID == id)
|
||||||
|
?? GameMain.Client.ConnectedClients.Find(c => c.ID == id)
|
||||||
|
?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => c.SteamID == id)
|
||||||
|
?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => c.ID == id);
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
public void SelectPlayer(GUITextBlock component, GUITextBlock.ClickableArea area)
|
public void SelectPlayer(GUITextBlock component, GUITextBlock.ClickableArea area)
|
||||||
{
|
{
|
||||||
if (!UInt64.TryParse(area.Data.Metadata, out UInt64 id)) { return; }
|
var client = ExtractClientFromClickableArea(area);
|
||||||
Client client = GameMain.Client.ConnectedClients.Find(c => c.SteamID == id)
|
if (client is null) { return; }
|
||||||
?? GameMain.Client.ConnectedClients.Find(c => c.ID == id)
|
|
||||||
?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => c.SteamID == id)
|
|
||||||
?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => c.ID == id);
|
|
||||||
if (client == null) { return; }
|
|
||||||
GameMain.NetLobbyScreen.SelectPlayer(client);
|
GameMain.NetLobbyScreen.SelectPlayer(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ShowPlayerContextMenu(GUITextBlock component, GUITextBlock.ClickableArea area)
|
||||||
|
{
|
||||||
|
var client = ExtractClientFromClickableArea(area);
|
||||||
|
if (client is null) { return; }
|
||||||
|
CreateModerationContextMenu(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Context Menu
|
||||||
|
public static void CreateModerationContextMenu(Client client)
|
||||||
|
{
|
||||||
|
if (GUIContextMenu.CurrentContextMenu != null) { return; }
|
||||||
|
if (GameMain.IsSingleplayer || client == null || ((!GameMain.Client?.PreviouslyConnectedClients?.Contains(client)) ?? true)) { return; }
|
||||||
|
bool hasSteam = client.SteamID > 0 && SteamManager.IsInitialized,
|
||||||
|
canKick = GameMain.Client.HasPermission(ClientPermissions.Kick),
|
||||||
|
canBan = GameMain.Client.HasPermission(ClientPermissions.Ban) && client.AllowKicking,
|
||||||
|
canPromo = GameMain.Client.HasPermission(ClientPermissions.ManagePermissions);
|
||||||
|
|
||||||
|
// Disable options if we are targeting ourselves
|
||||||
|
if (client.ID == GameMain.Client?.ID)
|
||||||
|
{
|
||||||
|
canKick = canBan = canPromo = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ContextMenuOption> options = new List<ContextMenuOption>();
|
||||||
|
|
||||||
|
options.Add(new ContextMenuOption("ViewSteamProfile", isEnabled: hasSteam, onSelected: delegate
|
||||||
|
{
|
||||||
|
Steamworks.SteamFriends.OpenWebOverlay($"https://steamcommunity.com/profiles/{client.SteamID}");
|
||||||
|
}));
|
||||||
|
|
||||||
|
options.Add(new ContextMenuOption("ModerationMenu.UserDetails", isEnabled: true, onSelected: delegate
|
||||||
|
{
|
||||||
|
GameMain.NetLobbyScreen?.SelectPlayer(client);
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
// Creates sub context menu options for all the ranks
|
||||||
|
List<ContextMenuOption> permissionOptions = new List<ContextMenuOption>();
|
||||||
|
foreach (PermissionPreset rank in PermissionPreset.List)
|
||||||
|
{
|
||||||
|
permissionOptions.Add(new ContextMenuOption(rank.Name, isEnabled: true, onSelected: () =>
|
||||||
|
{
|
||||||
|
string label = TextManager.GetWithVariables(rank.Permissions == ClientPermissions.None ? "clearrankprompt" : "giverankprompt", new []{ "[user]", "[rank]" }, new []{ client.Name, rank.Name });
|
||||||
|
GUIMessageBox msgBox = new GUIMessageBox(string.Empty, label, new[] { TextManager.Get("Yes"), TextManager.Get("Cancel") });
|
||||||
|
|
||||||
|
msgBox.Buttons[0].OnClicked = delegate
|
||||||
|
{
|
||||||
|
client.SetPermissions(rank.Permissions, rank.PermittedCommands);
|
||||||
|
GameMain.Client.UpdateClientPermissions(client);
|
||||||
|
msgBox.Close();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
msgBox.Buttons[1].OnClicked = delegate
|
||||||
|
{
|
||||||
|
msgBox.Close();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}) { Tooltip = rank.Description });
|
||||||
|
}
|
||||||
|
|
||||||
|
options.Add(new ContextMenuOption("Permissions", isEnabled: canPromo, options: permissionOptions.ToArray()));
|
||||||
|
|
||||||
|
Color clientColor = client.Character?.Info?.Job.Prefab.UIColor ?? Color.White;
|
||||||
|
|
||||||
|
if (GameMain.Client.ConnectedClients.Contains(client))
|
||||||
|
{
|
||||||
|
options.Add(new ContextMenuOption(client.MutedLocally ? "Unmute" : "Mute", isEnabled: client.ID != GameMain.Client?.ID, onSelected: delegate
|
||||||
|
{
|
||||||
|
client.MutedLocally = !client.MutedLocally;
|
||||||
|
}));
|
||||||
|
|
||||||
|
bool kickEnabled = client.ID != GameMain.Client?.ID && client.AllowKicking;
|
||||||
|
|
||||||
|
// if the user can kick create a kick option else create the votekick option
|
||||||
|
ContextMenuOption kickOption;
|
||||||
|
if (canKick)
|
||||||
|
{
|
||||||
|
kickOption = new ContextMenuOption("Kick", isEnabled: kickEnabled, onSelected: delegate
|
||||||
|
{
|
||||||
|
GameMain.Client?.CreateKickReasonPrompt(client.Name, false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
kickOption = new ContextMenuOption("VoteToKick", isEnabled: kickEnabled, onSelected: delegate
|
||||||
|
{
|
||||||
|
GameMain.Client?.VoteForKick(client);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
options.Add(kickOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
options.Add(new ContextMenuOption("Ban", isEnabled: canBan, onSelected: delegate
|
||||||
|
{
|
||||||
|
GameMain.Client?.CreateKickReasonPrompt(client.Name, true);
|
||||||
|
}));
|
||||||
|
|
||||||
|
GUIContextMenu.CreateContextMenu(null, client.Name, headerColor: clientColor, options.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
public bool SelectPlayer(Client selectedClient)
|
public bool SelectPlayer(Client selectedClient)
|
||||||
{
|
{
|
||||||
bool myClient = selectedClient.ID == GameMain.Client.ID;
|
bool myClient = selectedClient.ID == GameMain.Client.ID;
|
||||||
@@ -2763,7 +2821,8 @@ namespace Barotrauma
|
|||||||
msg.ClickableAreas.Add(new GUITextBlock.ClickableArea()
|
msg.ClickableAreas.Add(new GUITextBlock.ClickableArea()
|
||||||
{
|
{
|
||||||
Data = data,
|
Data = data,
|
||||||
OnClick = GameMain.NetLobbyScreen.SelectPlayer
|
OnClick = GameMain.NetLobbyScreen.SelectPlayer,
|
||||||
|
OnSecondaryClick = GameMain.NetLobbyScreen.ShowPlayerContextMenu
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3221,6 +3280,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
CreateSubPreview(submarine);
|
CreateSubPreview(submarine);
|
||||||
}
|
}
|
||||||
|
UpdateSubVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ViewJobInfo(GUIButton button, object obj)
|
private bool ViewJobInfo(GUIButton button, object obj)
|
||||||
@@ -3369,14 +3429,28 @@ namespace Barotrauma
|
|||||||
return btn;
|
return btn;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Pair<string, string> FailedSelectedSub;
|
public readonly struct FailedSubInfo
|
||||||
public Pair<string, string> FailedSelectedShuttle;
|
{
|
||||||
|
public readonly string Name;
|
||||||
|
public readonly string Hash;
|
||||||
|
public FailedSubInfo(string name, string hash) { Name = name; Hash = hash; }
|
||||||
|
public void Deconstruct(out string name, out string hash) { name = Name; hash = Hash; }
|
||||||
|
public static bool operator ==(FailedSubInfo a, FailedSubInfo b)
|
||||||
|
=> a.Name.Equals(b.Name, StringComparison.OrdinalIgnoreCase)
|
||||||
|
&& a.Hash.Equals(b.Hash, StringComparison.OrdinalIgnoreCase);
|
||||||
|
public static bool operator !=(FailedSubInfo a, FailedSubInfo b)
|
||||||
|
=> !(a == b);
|
||||||
|
}
|
||||||
|
|
||||||
public List<Pair<string, string>> FailedCampaignSubs = new List<Pair<string, string>>();
|
public FailedSubInfo? FailedSelectedSub;
|
||||||
public List<Pair<string, string>> FailedOwnedSubs = new List<Pair<string, string>>();
|
public FailedSubInfo? FailedSelectedShuttle;
|
||||||
|
|
||||||
|
public List<FailedSubInfo> FailedCampaignSubs = new List<FailedSubInfo>();
|
||||||
|
public List<FailedSubInfo> FailedOwnedSubs = new List<FailedSubInfo>();
|
||||||
|
|
||||||
public bool TrySelectSub(string subName, string md5Hash, GUIListBox subList)
|
public bool TrySelectSub(string subName, string md5Hash, GUIListBox subList)
|
||||||
{
|
{
|
||||||
|
UpdateSubVisibility();
|
||||||
if (GameMain.Client == null) { return false; }
|
if (GameMain.Client == null) { return false; }
|
||||||
|
|
||||||
//already downloading the selected sub file
|
//already downloading the selected sub file
|
||||||
@@ -3441,9 +3515,13 @@ namespace Barotrauma
|
|||||||
//if we get to this point, a matching sub was not found or it has an incorrect MD5 hash
|
//if we get to this point, a matching sub was not found or it has an incorrect MD5 hash
|
||||||
|
|
||||||
if (subList == SubList)
|
if (subList == SubList)
|
||||||
FailedSelectedSub = new Pair<string, string>(subName, md5Hash);
|
{
|
||||||
|
FailedSelectedSub = new FailedSubInfo(subName, md5Hash);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
FailedSelectedShuttle = new Pair<string, string>(subName, md5Hash);
|
{
|
||||||
|
FailedSelectedShuttle = new FailedSubInfo(subName, md5Hash);
|
||||||
|
}
|
||||||
|
|
||||||
string errorMsg = "";
|
string errorMsg = "";
|
||||||
if (sub == null || !SubmarineInfo.SavedSubmarines.Contains(sub))
|
if (sub == null || !SubmarineInfo.SavedSubmarines.Contains(sub))
|
||||||
@@ -3542,22 +3620,22 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
UserData = "request" + serverSubmarine.Name
|
UserData = "request" + serverSubmarine.Name
|
||||||
};
|
};
|
||||||
requestFileBox.Buttons[0].UserData = new string[] { serverSubmarine.Name, serverSubmarine.MD5Hash.Hash };
|
requestFileBox.Buttons[0].UserData = new FailedSubInfo(serverSubmarine.Name, serverSubmarine.MD5Hash.Hash);
|
||||||
requestFileBox.Buttons[0].OnClicked += requestFileBox.Close;
|
requestFileBox.Buttons[0].OnClicked += requestFileBox.Close;
|
||||||
requestFileBox.Buttons[0].OnClicked += (GUIButton button, object userdata) =>
|
requestFileBox.Buttons[0].OnClicked += (GUIButton button, object userdata) =>
|
||||||
{
|
{
|
||||||
string[] fileInfo = (string[])userdata;
|
FailedSubInfo fileInfo = (FailedSubInfo)userdata;
|
||||||
|
|
||||||
if (deliveryData == "owned")
|
if (deliveryData == "owned") //owned!!!!
|
||||||
{
|
{
|
||||||
FailedOwnedSubs.Add(new Pair<string, string>(fileInfo[0], fileInfo[1]));
|
FailedOwnedSubs.Add(fileInfo);
|
||||||
}
|
}
|
||||||
else if (deliveryData == "campaign")
|
else if (deliveryData == "campaign")
|
||||||
{
|
{
|
||||||
FailedCampaignSubs.Add(new Pair<string, string>(fileInfo[0], fileInfo[1]));
|
FailedCampaignSubs.Add(fileInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
GameMain.Client?.RequestFile(FileTransferType.Submarine, fileInfo[0], fileInfo[1]);
|
GameMain.Client?.RequestFile(FileTransferType.Submarine, fileInfo.Name, fileInfo.Hash);
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
requestFileBox.Buttons[1].OnClicked += requestFileBox.Close;
|
requestFileBox.Buttons[1].OnClicked += requestFileBox.Close;
|
||||||
@@ -3691,7 +3769,7 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
|
|
||||||
var subName = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), frameContent.RectTransform),
|
var subName = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), frameContent.RectTransform),
|
||||||
text: sub.Name)
|
text: sub.DisplayName)
|
||||||
{
|
{
|
||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
@@ -3823,7 +3901,9 @@ namespace Barotrauma
|
|||||||
foreach (GUIComponent child in SubList.Content.Children)
|
foreach (GUIComponent child in SubList.Content.Children)
|
||||||
{
|
{
|
||||||
if (!(child.UserData is SubmarineInfo sub)) { continue; }
|
if (!(child.UserData is SubmarineInfo sub)) { continue; }
|
||||||
child.Visible = !GameMain.Client.ServerSettings.HiddenSubs.Contains(sub.Name)
|
child.Visible =
|
||||||
|
(!GameMain.Client.ServerSettings.HiddenSubs.Contains(sub.Name)
|
||||||
|
|| (GameMain.GameSession?.SubmarineInfo != null && GameMain.GameSession.SubmarineInfo.Name.Equals(sub.Name, StringComparison.OrdinalIgnoreCase)))
|
||||||
&& (string.IsNullOrEmpty(subSearchBox.Text) || sub.DisplayName.Contains(subSearchBox.Text, StringComparison.OrdinalIgnoreCase));
|
&& (string.IsNullOrEmpty(subSearchBox.Text) || sub.DisplayName.Contains(subSearchBox.Text, StringComparison.OrdinalIgnoreCase));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2376,10 +2376,9 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
string errorMsg = "Failed to ping a server (" + ip + ") - " + (ex?.InnerException?.Message ?? ex.Message);
|
GameAnalyticsManager.AddErrorEventOnce("ServerListScreen.PingServer:PingException" + ip, GameAnalyticsManager.ErrorSeverity.Warning, "Failed to ping a server - " + (ex?.InnerException?.Message ?? ex.Message));
|
||||||
GameAnalyticsManager.AddErrorEventOnce("ServerListScreen.PingServer:PingException" + ip, GameAnalyticsSDK.Net.EGAErrorSeverity.Warning, errorMsg);
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
DebugConsole.NewMessage(errorMsg, Color.Red);
|
DebugConsole.NewMessage("Failed to ping a server (" + ip + ") - " + (ex?.InnerException?.Message ?? ex.Message), Color.Red);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -824,9 +824,8 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
string errorMsg = "Failed to save workshop item preview image to \"" + previewImagePath + "\".";
|
|
||||||
GameAnalyticsManager.AddErrorEventOnce("SteamWorkshopScreen.OnItemPreviewDownloaded:WriteAllBytesFailed" + previewImagePath,
|
GameAnalyticsManager.AddErrorEventOnce("SteamWorkshopScreen.OnItemPreviewDownloaded:WriteAllBytesFailed" + previewImagePath,
|
||||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg + "\n" + e.Message);
|
GameAnalyticsManager.ErrorSeverity.Error, "Failed to save workshop item preview image.\n" + e.Message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1195,7 +1194,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
string errorMsg = "Failed to edit workshop item (content package null)\n" + Environment.StackTrace.CleanupStackTrace();
|
string errorMsg = "Failed to edit workshop item (content package null)\n" + Environment.StackTrace.CleanupStackTrace();
|
||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("SteamWorkshopScreen.ShowCreateItemFrame:ContentPackageNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("SteamWorkshopScreen.ShowCreateItemFrame:ContentPackageNull", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -358,7 +358,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
displayName = TextManager.Get(fallbackTag, true);
|
displayName = TextManager.Get(fallbackTag, true) ?? TextManager.Get($"sp.{fallbackTag}.name", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ namespace Barotrauma.Sounds
|
|||||||
uint alSource = Sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex);
|
uint alSource = Sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex);
|
||||||
|
|
||||||
float effectiveGain = gain;
|
float effectiveGain = gain;
|
||||||
if (category != null) effectiveGain *= Sound.Owner.GetCategoryGainMultiplier(category);
|
if (category != null) { effectiveGain *= Sound.Owner.GetCategoryGainMultiplier(category); }
|
||||||
|
|
||||||
Al.Sourcef(alSource, Al.Gain, effectiveGain);
|
Al.Sourcef(alSource, Al.Gain, effectiveGain);
|
||||||
int alError = Al.GetError();
|
int alError = Al.GetError();
|
||||||
|
|||||||
@@ -470,14 +470,14 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
string errorMsg = "Failed to update water ambience volume - submarine's movement value invalid (" + movementSoundVolume + ", sub velocity: " + sub.Velocity + ")";
|
string errorMsg = "Failed to update water ambience volume - submarine's movement value invalid (" + movementSoundVolume + ", sub velocity: " + sub.Velocity + ")";
|
||||||
DebugConsole.Log(errorMsg);
|
DebugConsole.Log(errorMsg);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("SoundPlayer.UpdateWaterAmbience:InvalidVolume", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("SoundPlayer.UpdateWaterAmbience:InvalidVolume", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
movementSoundVolume = 0.0f;
|
movementSoundVolume = 0.0f;
|
||||||
}
|
}
|
||||||
if (!MathUtils.IsValid(insideSubFactor))
|
if (!MathUtils.IsValid(insideSubFactor))
|
||||||
{
|
{
|
||||||
string errorMsg = "Failed to update water ambience volume - inside sub value invalid (" + insideSubFactor + ")";
|
string errorMsg = "Failed to update water ambience volume - inside sub value invalid (" + insideSubFactor + ")";
|
||||||
DebugConsole.Log(errorMsg);
|
DebugConsole.Log(errorMsg);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("SoundPlayer.UpdateWaterAmbience:InvalidVolume", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("SoundPlayer.UpdateWaterAmbience:InvalidVolume", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
insideSubFactor = 0.0f;
|
insideSubFactor = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -609,7 +609,7 @@ namespace Barotrauma
|
|||||||
flowSoundChannels[i] = FlowSounds[i].Play(1.0f, FlowSoundRange, soundPos);
|
flowSoundChannels[i] = FlowSounds[i].Play(1.0f, FlowSoundRange, soundPos);
|
||||||
flowSoundChannels[i].Looping = true;
|
flowSoundChannels[i].Looping = true;
|
||||||
}
|
}
|
||||||
flowSoundChannels[i].Gain = Math.Max(flowVolumeRight[i], flowVolumeLeft[i]);
|
flowSoundChannels[i].Gain = Math.Min(Math.Max(flowVolumeRight[i], flowVolumeLeft[i]), 1.0f);
|
||||||
flowSoundChannels[i].Position = new Vector3(soundPos, 0.0f);
|
flowSoundChannels[i].Position = new Vector3(soundPos, 0.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -790,7 +790,7 @@ namespace Barotrauma
|
|||||||
if (sound == null)
|
if (sound == null)
|
||||||
{
|
{
|
||||||
string errorMsg = "Error in SoundPlayer.PlaySound (sound was null)\n" + Environment.StackTrace.CleanupStackTrace();
|
string errorMsg = "Error in SoundPlayer.PlaySound (sound was null)\n" + Environment.StackTrace.CleanupStackTrace();
|
||||||
GameAnalyticsManager.AddErrorEventOnce("SoundPlayer.PlaySound:SoundNull" + Environment.StackTrace.CleanupStackTrace(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("SoundPlayer.PlaySound:SoundNull" + Environment.StackTrace.CleanupStackTrace(), GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
float angle = 0.0f;
|
float angle = 0.0f;
|
||||||
float particleRotation = 0.0f;
|
float particleRotation = 0.0f;
|
||||||
|
bool mirrorAngle = false;
|
||||||
if (emitter.Prefab.Properties.CopyEntityAngle)
|
if (emitter.Prefab.Properties.CopyEntityAngle)
|
||||||
{
|
{
|
||||||
Limb targetLimb = null;
|
Limb targetLimb = null;
|
||||||
@@ -71,7 +72,11 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
angle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
angle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
||||||
particleRotation = -item.body.Rotation;
|
particleRotation = -item.body.Rotation;
|
||||||
if (item.body.Dir < 0.0f) { particleRotation += MathHelper.Pi; }
|
if (item.body.Dir < 0.0f)
|
||||||
|
{
|
||||||
|
particleRotation += MathHelper.Pi;
|
||||||
|
mirrorAngle = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (entity is Character c && !c.Removed && targetLimbs?.FirstOrDefault(l => l != LimbType.None) is LimbType l)
|
else if (entity is Character c && !c.Removed && targetLimbs?.FirstOrDefault(l => l != LimbType.None) is LimbType l)
|
||||||
{
|
{
|
||||||
@@ -85,11 +90,15 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
angle = targetLimb.body.Rotation + ((targetLimb.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
angle = targetLimb.body.Rotation + ((targetLimb.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
||||||
particleRotation = -targetLimb.body.Rotation;
|
particleRotation = -targetLimb.body.Rotation;
|
||||||
if (targetLimb.body.Dir < 0.0f) { particleRotation += MathHelper.Pi; }
|
if (targetLimb.body.Dir < 0.0f)
|
||||||
|
{
|
||||||
|
particleRotation += MathHelper.Pi;
|
||||||
|
mirrorAngle = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emitter.Emit(deltaTime, worldPosition, hull, angle: angle, particleRotation: particleRotation);
|
emitter.Emit(deltaTime, worldPosition, hull, angle: angle, particleRotation: particleRotation, mirrorAngle: mirrorAngle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +117,7 @@ namespace Barotrauma
|
|||||||
if (sound?.Sound == null)
|
if (sound?.Sound == null)
|
||||||
{
|
{
|
||||||
string errorMsg = $"Error in StatusEffect.ApplyProjSpecific1 (sound \"{sound?.Filename ?? "unknown"}\" was null)\n" + Environment.StackTrace.CleanupStackTrace();
|
string errorMsg = $"Error in StatusEffect.ApplyProjSpecific1 (sound \"{sound?.Filename ?? "unknown"}\" was null)\n" + Environment.StackTrace.CleanupStackTrace();
|
||||||
GameAnalyticsManager.AddErrorEventOnce("StatusEffect.ApplyProjSpecific:SoundNull1" + Environment.StackTrace.CleanupStackTrace(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("StatusEffect.ApplyProjSpecific:SoundNull1" + Environment.StackTrace.CleanupStackTrace(), GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
soundChannel = SoundPlayer.PlaySound(sound.Sound, worldPosition, sound.Volume, sound.Range, hullGuess: hull, ignoreMuffling: sound.IgnoreMuffling);
|
soundChannel = SoundPlayer.PlaySound(sound.Sound, worldPosition, sound.Volume, sound.Range, hullGuess: hull, ignoreMuffling: sound.IgnoreMuffling);
|
||||||
@@ -135,7 +144,7 @@ namespace Barotrauma
|
|||||||
if (selectedSound?.Sound == null)
|
if (selectedSound?.Sound == null)
|
||||||
{
|
{
|
||||||
string errorMsg = $"Error in StatusEffect.ApplyProjSpecific2 (sound \"{selectedSound?.Filename ?? "unknown"}\" was null)\n" + Environment.StackTrace.CleanupStackTrace();
|
string errorMsg = $"Error in StatusEffect.ApplyProjSpecific2 (sound \"{selectedSound?.Filename ?? "unknown"}\" was null)\n" + Environment.StackTrace.CleanupStackTrace();
|
||||||
GameAnalyticsManager.AddErrorEventOnce("StatusEffect.ApplyProjSpecific:SoundNull2" + Environment.StackTrace.CleanupStackTrace(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("StatusEffect.ApplyProjSpecific:SoundNull2" + Environment.StackTrace.CleanupStackTrace(), GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (selectedSound.Sound.Disposed)
|
if (selectedSound.Sound.Disposed)
|
||||||
|
|||||||
@@ -421,7 +421,7 @@ namespace Barotrauma
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
DebugConsole.ThrowError("Empty color array passed to the GradientLerp method.\n" + Environment.StackTrace.CleanupStackTrace());
|
DebugConsole.ThrowError("Empty color array passed to the GradientLerp method.\n" + Environment.StackTrace.CleanupStackTrace());
|
||||||
#endif
|
#endif
|
||||||
GameAnalyticsManager.AddErrorEventOnce("ToolBox.GradientLerp:EmptyColorArray", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
GameAnalyticsManager.AddErrorEventOnce("ToolBox.GradientLerp:EmptyColorArray", GameAnalyticsManager.ErrorSeverity.Error,
|
||||||
"Empty color array passed to the GradientLerp method.\n" + Environment.StackTrace.CleanupStackTrace());
|
"Empty color array passed to the GradientLerp method.\n" + Environment.StackTrace.CleanupStackTrace());
|
||||||
return Color.Black;
|
return Color.Black;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.15.15.0</Version>
|
<Version>0.15.17.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>
|
||||||
@@ -55,6 +55,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="..\BarotraumaShared\**\*" CopyToOutputDirectory="PreserveNewest" />
|
<Content Include="..\BarotraumaShared\**\*" CopyToOutputDirectory="PreserveNewest" />
|
||||||
<Content Remove="..\BarotraumaShared\**\*.cs" />
|
<Content Remove="..\BarotraumaShared\**\*.cs" />
|
||||||
|
<Content Remove="..\BarotraumaShared\**\*.props" />
|
||||||
<Compile Include="..\BarotraumaShared\**\*.cs" />
|
<Compile Include="..\BarotraumaShared\**\*.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
@@ -99,7 +100,6 @@
|
|||||||
<ProjectReference Include="..\..\Libraries\Concentus\CSharp\Concentus\Concentus.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Concentus\CSharp\Concentus\Concentus.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
<ProjectReference Include="..\..\Libraries\Facepunch.Steamworks\Facepunch.Steamworks.Posix.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Facepunch.Steamworks\Facepunch.Steamworks.Posix.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
<ProjectReference Include="..\..\Libraries\Farseer Physics Engine 3.5\Farseer.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Farseer Physics Engine 3.5\Farseer.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
<ProjectReference Include="..\..\Libraries\GameAnalytics\GA_SDK_NETSTANDARD\GA_SDK_NETSTANDARD.csproj" AdditionalProperties="Configuration=Release" />
|
|
||||||
<ProjectReference Include="..\..\Libraries\Hyper.ComponentModel\Hyper.ComponentModel.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Hyper.ComponentModel\Hyper.ComponentModel.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
<ProjectReference Include="..\..\Libraries\Lidgren.Network\Lidgren.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Lidgren.Network\Lidgren.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
<ProjectReference Include="..\..\Libraries\MonoGame.Framework\Src\MonoGame.Framework\MonoGame.Framework.Linux.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\MonoGame.Framework\Src\MonoGame.Framework\MonoGame.Framework.Linux.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
@@ -109,7 +109,6 @@
|
|||||||
<ProjectReference Include="..\..\Libraries\Concentus\CSharp\Concentus\Concentus.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Concentus\CSharp\Concentus\Concentus.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\Facepunch.Steamworks\Facepunch.Steamworks.Posix.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Facepunch.Steamworks\Facepunch.Steamworks.Posix.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\Farseer Physics Engine 3.5\Farseer.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Farseer Physics Engine 3.5\Farseer.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\GameAnalytics\GA_SDK_NETSTANDARD\GA_SDK_NETSTANDARD.csproj" AdditionalProperties="Configuration=Debug" />
|
|
||||||
<ProjectReference Include="..\..\Libraries\Hyper.ComponentModel\Hyper.ComponentModel.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Hyper.ComponentModel\Hyper.ComponentModel.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\Lidgren.Network\Lidgren.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Lidgren.Network\Lidgren.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\MonoGame.Framework\Src\MonoGame.Framework\MonoGame.Framework.Linux.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\MonoGame.Framework\Src\MonoGame.Framework\MonoGame.Framework.Linux.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
@@ -189,4 +188,9 @@
|
|||||||
<WriteCodeFragment Language="C#" OutputFile="$(CustomAssemblyInfoFile)" AssemblyAttributes="@(AssemblyAttributes)" />
|
<WriteCodeFragment Language="C#" OutputFile="$(CustomAssemblyInfoFile)" AssemblyAttributes="@(AssemblyAttributes)" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<GARuntime>linux-x64</GARuntime>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="../BarotraumaShared/DeployGameAnalytics.props" />
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -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.15.15.0</Version>
|
<Version>0.15.17.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>
|
||||||
@@ -58,6 +58,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="..\BarotraumaShared\**\*" CopyToOutputDirectory="PreserveNewest" />
|
<Content Include="..\BarotraumaShared\**\*" CopyToOutputDirectory="PreserveNewest" />
|
||||||
<Content Remove="..\BarotraumaShared\**\*.cs" />
|
<Content Remove="..\BarotraumaShared\**\*.cs" />
|
||||||
|
<Content Remove="..\BarotraumaShared\**\*.props" />
|
||||||
<Compile Include="..\BarotraumaShared\**\*.cs" />
|
<Compile Include="..\BarotraumaShared\**\*.cs" />
|
||||||
<Content Remove="..\BarotraumaShared\libsteam_api64.dylib" />
|
<Content Remove="..\BarotraumaShared\libsteam_api64.dylib" />
|
||||||
<Content Remove="..\BarotraumaShared\libsteam_api64.so" />
|
<Content Remove="..\BarotraumaShared\libsteam_api64.so" />
|
||||||
@@ -100,7 +101,6 @@
|
|||||||
<ProjectReference Include="..\..\Libraries\Concentus\CSharp\Concentus\Concentus.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Concentus\CSharp\Concentus\Concentus.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
<ProjectReference Include="..\..\Libraries\Facepunch.Steamworks\Facepunch.Steamworks.Posix.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Facepunch.Steamworks\Facepunch.Steamworks.Posix.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
<ProjectReference Include="..\..\Libraries\Farseer Physics Engine 3.5\Farseer.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Farseer Physics Engine 3.5\Farseer.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
<ProjectReference Include="..\..\Libraries\GameAnalytics\GA_SDK_NETSTANDARD\GA_SDK_NETSTANDARD.csproj" AdditionalProperties="Configuration=Release" />
|
|
||||||
<ProjectReference Include="..\..\Libraries\Hyper.ComponentModel\Hyper.ComponentModel.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Hyper.ComponentModel\Hyper.ComponentModel.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
<ProjectReference Include="..\..\Libraries\Lidgren.Network\Lidgren.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Lidgren.Network\Lidgren.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
<ProjectReference Include="..\..\Libraries\SharpFont\Source\SharpFont\SharpFont.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\SharpFont\Source\SharpFont\SharpFont.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
@@ -110,7 +110,6 @@
|
|||||||
<ProjectReference Include="..\..\Libraries\Concentus\CSharp\Concentus\Concentus.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Concentus\CSharp\Concentus\Concentus.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\Facepunch.Steamworks\Facepunch.Steamworks.Posix.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Facepunch.Steamworks\Facepunch.Steamworks.Posix.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\Farseer Physics Engine 3.5\Farseer.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Farseer Physics Engine 3.5\Farseer.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\GameAnalytics\GA_SDK_NETSTANDARD\GA_SDK_NETSTANDARD.csproj" AdditionalProperties="Configuration=Debug" />
|
|
||||||
<ProjectReference Include="..\..\Libraries\Hyper.ComponentModel\Hyper.ComponentModel.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Hyper.ComponentModel\Hyper.ComponentModel.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\Lidgren.Network\Lidgren.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Lidgren.Network\Lidgren.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\SharpFont\Source\SharpFont\SharpFont.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\SharpFont\Source\SharpFont\SharpFont.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
@@ -201,4 +200,9 @@
|
|||||||
<WriteCodeFragment Language="C#" OutputFile="$(CustomAssemblyInfoFile)" AssemblyAttributes="@(AssemblyAttributes)" />
|
<WriteCodeFragment Language="C#" OutputFile="$(CustomAssemblyInfoFile)" AssemblyAttributes="@(AssemblyAttributes)" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<GARuntime>osx-x64</GARuntime>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="../BarotraumaShared/DeployGameAnalytics.props" />
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -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.15.15.0</Version>
|
<Version>0.15.17.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>
|
||||||
@@ -63,6 +63,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="..\BarotraumaShared\**\*" CopyToOutputDirectory="PreserveNewest" />
|
<Content Include="..\BarotraumaShared\**\*" CopyToOutputDirectory="PreserveNewest" />
|
||||||
<Content Remove="..\BarotraumaShared\**\*.cs" />
|
<Content Remove="..\BarotraumaShared\**\*.cs" />
|
||||||
|
<Content Remove="..\BarotraumaShared\**\*.props" />
|
||||||
<Compile Include="..\BarotraumaShared\**\*.cs" />
|
<Compile Include="..\BarotraumaShared\**\*.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
@@ -103,7 +104,6 @@
|
|||||||
<ProjectReference Include="..\..\Libraries\Concentus\CSharp\Concentus\Concentus.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Concentus\CSharp\Concentus\Concentus.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
<ProjectReference Include="..\..\Libraries\Facepunch.Steamworks\Facepunch.Steamworks.Win64.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Facepunch.Steamworks\Facepunch.Steamworks.Win64.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
<ProjectReference Include="..\..\Libraries\Farseer Physics Engine 3.5\Farseer.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Farseer Physics Engine 3.5\Farseer.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
<ProjectReference Include="..\..\Libraries\GameAnalytics\GA_SDK_NETSTANDARD\GA_SDK_NETSTANDARD.csproj" AdditionalProperties="Configuration=Release" />
|
|
||||||
<ProjectReference Include="..\..\Libraries\Hyper.ComponentModel\Hyper.ComponentModel.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Hyper.ComponentModel\Hyper.ComponentModel.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
<ProjectReference Include="..\..\Libraries\Lidgren.Network\Lidgren.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Lidgren.Network\Lidgren.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
<ProjectReference Include="..\..\Libraries\MonoGame.Framework\Src\MonoGame.Framework\MonoGame.Framework.Windows.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\MonoGame.Framework\Src\MonoGame.Framework\MonoGame.Framework.Windows.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
@@ -113,7 +113,6 @@
|
|||||||
<ProjectReference Include="..\..\Libraries\Concentus\CSharp\Concentus\Concentus.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Concentus\CSharp\Concentus\Concentus.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\Facepunch.Steamworks\Facepunch.Steamworks.Win64.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Facepunch.Steamworks\Facepunch.Steamworks.Win64.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\Farseer Physics Engine 3.5\Farseer.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Farseer Physics Engine 3.5\Farseer.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\GameAnalytics\GA_SDK_NETSTANDARD\GA_SDK_NETSTANDARD.csproj" AdditionalProperties="Configuration=Debug" />
|
|
||||||
<ProjectReference Include="..\..\Libraries\Hyper.ComponentModel\Hyper.ComponentModel.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Hyper.ComponentModel\Hyper.ComponentModel.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\Lidgren.Network\Lidgren.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Lidgren.Network\Lidgren.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\MonoGame.Framework\Src\MonoGame.Framework\MonoGame.Framework.Windows.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\MonoGame.Framework\Src\MonoGame.Framework\MonoGame.Framework.Windows.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
@@ -220,4 +219,9 @@
|
|||||||
<WriteCodeFragment Language="C#" OutputFile="$(CustomAssemblyInfoFile)" AssemblyAttributes="@(AssemblyAttributes)" />
|
<WriteCodeFragment Language="C#" OutputFile="$(CustomAssemblyInfoFile)" AssemblyAttributes="@(AssemblyAttributes)" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<GARuntime>win-x64</GARuntime>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="../BarotraumaShared/DeployGameAnalytics.props" />
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -1,62 +1,62 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
|
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
|
||||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||||
<security>
|
<security>
|
||||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||||
</requestedPrivileges>
|
</requestedPrivileges>
|
||||||
</security>
|
</security>
|
||||||
</trustInfo>
|
</trustInfo>
|
||||||
|
|
||||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||||
<application>
|
<application>
|
||||||
<!-- A list of the Windows versions that this application has been tested on
|
<!-- A list of the Windows versions that this application has been tested on
|
||||||
and is designed to work with. Uncomment the appropriate elements
|
and is designed to work with. Uncomment the appropriate elements
|
||||||
and Windows will automatically select the most compatible environment. -->
|
and Windows will automatically select the most compatible environment. -->
|
||||||
|
|
||||||
<!-- Windows Vista -->
|
<!-- Windows Vista -->
|
||||||
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
|
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
|
||||||
|
|
||||||
<!-- Windows 7 -->
|
<!-- Windows 7 -->
|
||||||
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
|
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
|
||||||
|
|
||||||
<!-- Windows 8 -->
|
<!-- Windows 8 -->
|
||||||
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
|
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
|
||||||
|
|
||||||
<!-- Windows 8.1 -->
|
<!-- Windows 8.1 -->
|
||||||
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
|
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
|
||||||
|
|
||||||
<!-- Windows 10 -->
|
<!-- Windows 10 -->
|
||||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
</compatibility>
|
</compatibility>
|
||||||
|
|
||||||
<!-- Indicates that the application is DPI-aware and will not be automatically scaled by Windows at higher
|
<!-- Indicates that the application is DPI-aware and will not be automatically scaled by Windows at higher
|
||||||
DPIs. Windows Presentation Foundation (WPF) applications are automatically DPI-aware and do not need
|
DPIs. Windows Presentation Foundation (WPF) applications are automatically DPI-aware and do not need
|
||||||
to opt in. Windows Forms applications targeting .NET Framework 4.6 that opt into this setting, should
|
to opt in. Windows Forms applications targeting .NET Framework 4.6 that opt into this setting, should
|
||||||
also set the 'EnableWindowsFormsHighDpiAutoResizing' setting to 'true' in their app.config. -->
|
also set the 'EnableWindowsFormsHighDpiAutoResizing' setting to 'true' in their app.config. -->
|
||||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
<windowsSettings>
|
<windowsSettings>
|
||||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware>
|
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware>
|
||||||
</windowsSettings>
|
</windowsSettings>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
<!-- Enable themes for Windows common controls and dialogs (Windows XP and later) -->
|
<!-- Enable themes for Windows common controls and dialogs (Windows XP and later) -->
|
||||||
<!--
|
<!--
|
||||||
<dependency>
|
<dependency>
|
||||||
<dependentAssembly>
|
<dependentAssembly>
|
||||||
<assemblyIdentity
|
<assemblyIdentity
|
||||||
type="win32"
|
type="win32"
|
||||||
name="Microsoft.Windows.Common-Controls"
|
name="Microsoft.Windows.Common-Controls"
|
||||||
version="6.0.0.0"
|
version="6.0.0.0"
|
||||||
processorArchitecture="*"
|
processorArchitecture="*"
|
||||||
publicKeyToken="6595b64144ccf1df"
|
publicKeyToken="6595b64144ccf1df"
|
||||||
language="*"
|
language="*"
|
||||||
/>
|
/>
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
</dependency>
|
</dependency>
|
||||||
-->
|
-->
|
||||||
|
|
||||||
</assembly>
|
</assembly>
|
||||||
|
|||||||
@@ -1,141 +1,144 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
<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.15.15.0</Version>
|
<Version>0.15.17.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>
|
||||||
<ApplicationIcon>..\BarotraumaShared\Icon.ico</ApplicationIcon>
|
<ApplicationIcon>..\BarotraumaShared\Icon.ico</ApplicationIcon>
|
||||||
<Configurations>Debug;Release;Unstable</Configurations>
|
<Configurations>Debug;Release;Unstable</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
<DefineConstants>DEBUG;TRACE;SERVER;LINUX;USE_STEAM</DefineConstants>
|
<DefineConstants>DEBUG;TRACE;SERVER;LINUX;USE_STEAM</DefineConstants>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<OutputPath>..\bin\$(Configuration)Linux\</OutputPath>
|
<OutputPath>..\bin\$(Configuration)Linux\</OutputPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<DefineConstants>TRACE;DEBUG;SERVER;LINUX;X64;USE_STEAM</DefineConstants>
|
<DefineConstants>TRACE;DEBUG;SERVER;LINUX;X64;USE_STEAM</DefineConstants>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<OutputPath>..\bin\$(Configuration)Linux\</OutputPath>
|
<OutputPath>..\bin\$(Configuration)Linux\</OutputPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
<DefineConstants>TRACE;SERVER;LINUX;USE_STEAM</DefineConstants>
|
<DefineConstants>TRACE;SERVER;LINUX;USE_STEAM</DefineConstants>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<OutputPath>..\bin\$(Configuration)Linux\</OutputPath>
|
<OutputPath>..\bin\$(Configuration)Linux\</OutputPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unstable|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unstable|AnyCPU'">
|
||||||
<DefineConstants>TRACE;SERVER;LINUX;USE_STEAM</DefineConstants>
|
<DefineConstants>TRACE;SERVER;LINUX;USE_STEAM</DefineConstants>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<OutputPath>..\bin\$(Configuration)Linux\</OutputPath>
|
<OutputPath>..\bin\$(Configuration)Linux\</OutputPath>
|
||||||
<Optimize>true</Optimize>
|
<Optimize>true</Optimize>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<DefineConstants>TRACE;SERVER;LINUX;X64;USE_STEAM</DefineConstants>
|
<DefineConstants>TRACE;SERVER;LINUX;X64;USE_STEAM</DefineConstants>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<OutputPath>..\bin\$(Configuration)Linux\</OutputPath>
|
<OutputPath>..\bin\$(Configuration)Linux\</OutputPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unstable|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unstable|x64'">
|
||||||
<DefineConstants>TRACE;SERVER;LINUX;X64;USE_STEAM</DefineConstants>
|
<DefineConstants>TRACE;SERVER;LINUX;X64;USE_STEAM</DefineConstants>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<OutputPath>..\bin\$(Configuration)Linux\</OutputPath>
|
<OutputPath>..\bin\$(Configuration)Linux\</OutputPath>
|
||||||
<Optimize>true</Optimize>
|
<Optimize>true</Optimize>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="..\BarotraumaShared\**\*" CopyToOutputDirectory="PreserveNewest" />
|
<Content Include="..\BarotraumaShared\**\*" CopyToOutputDirectory="PreserveNewest" />
|
||||||
<Content Remove="..\BarotraumaShared\**\*.cs" />
|
<Content Remove="..\BarotraumaShared\**\*.cs" />
|
||||||
<Compile Include="..\BarotraumaShared\**\*.cs" />
|
<Content Remove="..\BarotraumaShared\**\*.props" />
|
||||||
<Content Include="DedicatedServer.exe" CopyToOutputDirectory="PreserveNewest" />
|
<Compile Include="..\BarotraumaShared\**\*.cs" />
|
||||||
</ItemGroup>
|
<Content Include="DedicatedServer.exe" CopyToOutputDirectory="PreserveNewest" />
|
||||||
|
</ItemGroup>
|
||||||
<ItemGroup Condition="'$(Configuration)'!='Debug'">
|
|
||||||
<ProjectReference Include="..\..\Libraries\Facepunch.Steamworks\Facepunch.Steamworks.Posix.csproj" AdditionalProperties="Configuration=Release" />
|
<ItemGroup Condition="'$(Configuration)'!='Debug'">
|
||||||
<ProjectReference Include="..\..\Libraries\Farseer Physics Engine 3.5\Farseer.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Facepunch.Steamworks\Facepunch.Steamworks.Posix.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
<ProjectReference Include="..\..\Libraries\GameAnalytics\GA_SDK_NETSTANDARD\GA_SDK_NETSTANDARD.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Farseer Physics Engine 3.5\Farseer.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
<ProjectReference Include="..\..\Libraries\Hyper.ComponentModel\Hyper.ComponentModel.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Hyper.ComponentModel\Hyper.ComponentModel.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
<ProjectReference Include="..\..\Libraries\Lidgren.Network\Lidgren.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Lidgren.Network\Lidgren.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Condition="'$(Configuration)'=='Debug'">
|
<ItemGroup Condition="'$(Configuration)'=='Debug'">
|
||||||
<ProjectReference Include="..\..\Libraries\Facepunch.Steamworks\Facepunch.Steamworks.Posix.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Facepunch.Steamworks\Facepunch.Steamworks.Posix.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\Farseer Physics Engine 3.5\Farseer.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Farseer Physics Engine 3.5\Farseer.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\GameAnalytics\GA_SDK_NETSTANDARD\GA_SDK_NETSTANDARD.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Hyper.ComponentModel\Hyper.ComponentModel.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\Hyper.ComponentModel\Hyper.ComponentModel.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Lidgren.Network\Lidgren.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\Lidgren.Network\Lidgren.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
</ItemGroup>
|
||||||
</ItemGroup>
|
|
||||||
|
<ItemGroup>
|
||||||
<!-- Sourced from https://stackoverflow.com/a/45248069 -->
|
<PackageReference Include="RestSharp" Version="106.13.0" />
|
||||||
<Target Name="GetGitRevision" BeforeTargets="WriteGitRevision" Condition="'$(BuildHash)' == ''">
|
</ItemGroup>
|
||||||
<PropertyGroup>
|
|
||||||
<!-- temp file for the git version (lives in "obj" folder)-->
|
<!-- Sourced from https://stackoverflow.com/a/45248069 -->
|
||||||
<VerFile>$(IntermediateOutputPath)gitver</VerFile>
|
<Target Name="GetGitRevision" BeforeTargets="WriteGitRevision" Condition="'$(BuildHash)' == ''">
|
||||||
<BranchFile>$(IntermediateOutputPath)gitbranch</BranchFile>
|
<PropertyGroup>
|
||||||
</PropertyGroup>
|
<!-- temp file for the git version (lives in "obj" folder)-->
|
||||||
|
<VerFile>$(IntermediateOutputPath)gitver</VerFile>
|
||||||
<!-- write the hash to the temp file.-->
|
<BranchFile>$(IntermediateOutputPath)gitbranch</BranchFile>
|
||||||
<Exec Command="git -C $(ProjectDir) rev-parse --short HEAD > $(VerFile)" ContinueOnError="true">
|
</PropertyGroup>
|
||||||
<Output TaskParameter="exitcode" ItemName="exitcodes" />
|
|
||||||
</Exec>
|
<!-- write the hash to the temp file.-->
|
||||||
<Exec Command="git -C $(ProjectDir) rev-parse --short HEAD --symbolic-full-name --abbrev-ref=strict > $(BranchFile)" ContinueOnError="true" />
|
<Exec Command="git -C $(ProjectDir) rev-parse --short HEAD > $(VerFile)" ContinueOnError="true">
|
||||||
|
<Output TaskParameter="exitcode" ItemName="exitcodes" />
|
||||||
<Exec Command="echo GIT_UNAVAILABLE > $(VerFile)" Condition="'%(exitcodes.identity)'>0" />
|
</Exec>
|
||||||
<Exec Command="echo GIT_UNAVAILABLE > $(BranchFile)" Condition="'%(exitcodes.identity)'>0" />
|
<Exec Command="git -C $(ProjectDir) rev-parse --short HEAD --symbolic-full-name --abbrev-ref=strict > $(BranchFile)" ContinueOnError="true" />
|
||||||
|
|
||||||
<!-- read the version into the GitVersion itemGroup-->
|
<Exec Command="echo GIT_UNAVAILABLE > $(VerFile)" Condition="'%(exitcodes.identity)'>0" />
|
||||||
<ReadLinesFromFile File="$(VerFile)">
|
<Exec Command="echo GIT_UNAVAILABLE > $(BranchFile)" Condition="'%(exitcodes.identity)'>0" />
|
||||||
<Output TaskParameter="Lines" ItemName="GitVersion" />
|
|
||||||
</ReadLinesFromFile>
|
<!-- read the version into the GitVersion itemGroup-->
|
||||||
<!-- Set the BuildHash property to contain the GitVersion, if it wasn't already set.-->
|
<ReadLinesFromFile File="$(VerFile)">
|
||||||
<PropertyGroup>
|
<Output TaskParameter="Lines" ItemName="GitVersion" />
|
||||||
<BuildHash>@(GitVersion)</BuildHash>
|
</ReadLinesFromFile>
|
||||||
</PropertyGroup>
|
<!-- Set the BuildHash property to contain the GitVersion, if it wasn't already set.-->
|
||||||
|
<PropertyGroup>
|
||||||
<!-- read the branch into the GitBranch itemGroup-->
|
<BuildHash>@(GitVersion)</BuildHash>
|
||||||
<ReadLinesFromFile File="$(BranchFile)">
|
</PropertyGroup>
|
||||||
<Output TaskParameter="Lines" ItemName="GitBranch" />
|
|
||||||
</ReadLinesFromFile>
|
<!-- read the branch into the GitBranch itemGroup-->
|
||||||
<!-- Set the BuildHash property to contain the GitVersion, if it wasn't already set.-->
|
<ReadLinesFromFile File="$(BranchFile)">
|
||||||
<PropertyGroup>
|
<Output TaskParameter="Lines" ItemName="GitBranch" />
|
||||||
<BuildBranch>@(GitBranch)</BuildBranch>
|
</ReadLinesFromFile>
|
||||||
</PropertyGroup>
|
<!-- Set the BuildHash property to contain the GitVersion, if it wasn't already set.-->
|
||||||
</Target>
|
<PropertyGroup>
|
||||||
|
<BuildBranch>@(GitBranch)</BuildBranch>
|
||||||
<Target Name="WriteGitRevision" BeforeTargets="CoreCompile">
|
</PropertyGroup>
|
||||||
<!-- names the obj/.../CustomAssemblyInfo.cs file -->
|
</Target>
|
||||||
<PropertyGroup>
|
|
||||||
<CustomAssemblyInfoFile>$(IntermediateOutputPath)CustomAssemblyInfo.cs</CustomAssemblyInfoFile>
|
<Target Name="WriteGitRevision" BeforeTargets="CoreCompile">
|
||||||
</PropertyGroup>
|
<!-- names the obj/.../CustomAssemblyInfo.cs file -->
|
||||||
<!-- includes the CustomAssemblyInfo for compilation into your project -->
|
<PropertyGroup>
|
||||||
<ItemGroup>
|
<CustomAssemblyInfoFile>$(IntermediateOutputPath)CustomAssemblyInfo.cs</CustomAssemblyInfoFile>
|
||||||
<Compile Include="$(CustomAssemblyInfoFile)" />
|
</PropertyGroup>
|
||||||
</ItemGroup>
|
<!-- includes the CustomAssemblyInfo for compilation into your project -->
|
||||||
<!-- defines the AssemblyMetadata attribute that will be written -->
|
<ItemGroup>
|
||||||
<ItemGroup>
|
<Compile Include="$(CustomAssemblyInfoFile)" />
|
||||||
<AssemblyAttributes Include="AssemblyMetadata">
|
</ItemGroup>
|
||||||
<_Parameter1>GitRevision</_Parameter1>
|
<!-- defines the AssemblyMetadata attribute that will be written -->
|
||||||
<_Parameter2>$(BuildHash)</_Parameter2>
|
<ItemGroup>
|
||||||
</AssemblyAttributes>
|
<AssemblyAttributes Include="AssemblyMetadata">
|
||||||
<AssemblyAttributes Include="AssemblyMetadata">
|
<_Parameter1>GitRevision</_Parameter1>
|
||||||
<_Parameter1>GitBranch</_Parameter1>
|
<_Parameter2>$(BuildHash)</_Parameter2>
|
||||||
<_Parameter2>$(BuildBranch)</_Parameter2>
|
</AssemblyAttributes>
|
||||||
</AssemblyAttributes>
|
<AssemblyAttributes Include="AssemblyMetadata">
|
||||||
<AssemblyAttributes Include="AssemblyMetadata">
|
<_Parameter1>GitBranch</_Parameter1>
|
||||||
<_Parameter1>ProjectDir</_Parameter1>
|
<_Parameter2>$(BuildBranch)</_Parameter2>
|
||||||
<_Parameter2>$(ProjectDir)</_Parameter2>
|
</AssemblyAttributes>
|
||||||
</AssemblyAttributes>
|
<AssemblyAttributes Include="AssemblyMetadata">
|
||||||
</ItemGroup>
|
<_Parameter1>ProjectDir</_Parameter1>
|
||||||
<!-- writes the attribute to the customAssemblyInfo file -->
|
<_Parameter2>$(ProjectDir)</_Parameter2>
|
||||||
<WriteCodeFragment Language="C#" OutputFile="$(CustomAssemblyInfoFile)" AssemblyAttributes="@(AssemblyAttributes)" />
|
</AssemblyAttributes>
|
||||||
</Target>
|
</ItemGroup>
|
||||||
|
<!-- writes the attribute to the customAssemblyInfo file -->
|
||||||
</Project>
|
<WriteCodeFragment Language="C#" OutputFile="$(CustomAssemblyInfoFile)" AssemblyAttributes="@(AssemblyAttributes)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|||||||
@@ -1,154 +1,157 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
<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.15.15.0</Version>
|
<Version>0.15.17.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>
|
||||||
<ApplicationIcon>..\BarotraumaShared\Icon.ico</ApplicationIcon>
|
<ApplicationIcon>..\BarotraumaShared\Icon.ico</ApplicationIcon>
|
||||||
<ReleaseVersion>0.9.0.0</ReleaseVersion>
|
<ReleaseVersion>0.9.0.0</ReleaseVersion>
|
||||||
<Configurations>Debug;Release;Unstable</Configurations>
|
<Configurations>Debug;Release;Unstable</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
<DefineConstants>TRACE;SERVER;OSX;USE_STEAM;DEBUG;NETCOREAPP;NETCOREAPP3_0</DefineConstants>
|
<DefineConstants>TRACE;SERVER;OSX;USE_STEAM;DEBUG;NETCOREAPP;NETCOREAPP3_0</DefineConstants>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<OutputPath>..\bin\DebugMac</OutputPath>
|
<OutputPath>..\bin\DebugMac</OutputPath>
|
||||||
<ConsolePause>true</ConsolePause>
|
<ConsolePause>true</ConsolePause>
|
||||||
<CheckForOverflowUnderflow></CheckForOverflowUnderflow>
|
<CheckForOverflowUnderflow></CheckForOverflowUnderflow>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<DefineConstants>TRACE;DEBUG;SERVER;OSX;X64;USE_STEAM</DefineConstants>
|
<DefineConstants>TRACE;DEBUG;SERVER;OSX;X64;USE_STEAM</DefineConstants>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<OutputPath>..\bin\$(Configuration)Mac\</OutputPath>
|
<OutputPath>..\bin\$(Configuration)Mac\</OutputPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
<DefineConstants>TRACE;SERVER;OSX;USE_STEAM;RELEASE;NETCOREAPP;NETCOREAPP3_0</DefineConstants>
|
<DefineConstants>TRACE;SERVER;OSX;USE_STEAM;RELEASE;NETCOREAPP;NETCOREAPP3_0</DefineConstants>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<DebugType></DebugType>
|
<DebugType></DebugType>
|
||||||
<OutputPath>..\bin\ReleaseMac</OutputPath>
|
<OutputPath>..\bin\ReleaseMac</OutputPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unstable|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unstable|AnyCPU'">
|
||||||
<DefineConstants>TRACE;SERVER;OSX;USE_STEAM;RELEASE;NETCOREAPP;NETCOREAPP3_0;UNSTABLE</DefineConstants>
|
<DefineConstants>TRACE;SERVER;OSX;USE_STEAM;RELEASE;NETCOREAPP;NETCOREAPP3_0;UNSTABLE</DefineConstants>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<DebugType />
|
<DebugType />
|
||||||
<OutputPath>..\bin\ReleaseMac</OutputPath>
|
<OutputPath>..\bin\ReleaseMac</OutputPath>
|
||||||
<Optimize>true</Optimize>
|
<Optimize>true</Optimize>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<DefineConstants>TRACE;SERVER;OSX;X64;USE_STEAM</DefineConstants>
|
<DefineConstants>TRACE;SERVER;OSX;X64;USE_STEAM</DefineConstants>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<OutputPath>..\bin\$(Configuration)Mac\</OutputPath>
|
<OutputPath>..\bin\$(Configuration)Mac\</OutputPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unstable|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unstable|x64'">
|
||||||
<DefineConstants>TRACE;SERVER;OSX;X64;USE_STEAM;UNSTABLE</DefineConstants>
|
<DefineConstants>TRACE;SERVER;OSX;X64;USE_STEAM;UNSTABLE</DefineConstants>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<OutputPath>..\bin\$(Configuration)Mac\</OutputPath>
|
<OutputPath>..\bin\$(Configuration)Mac\</OutputPath>
|
||||||
<Optimize>true</Optimize>
|
<Optimize>true</Optimize>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="..\BarotraumaShared\**\*" CopyToOutputDirectory="PreserveNewest" />
|
<Content Include="..\BarotraumaShared\**\*" CopyToOutputDirectory="PreserveNewest" />
|
||||||
<Content Remove="..\BarotraumaShared\**\*.cs" />
|
<Content Remove="..\BarotraumaShared\**\*.cs" />
|
||||||
<Compile Include="..\BarotraumaShared\**\*.cs" />
|
<Content Remove="..\BarotraumaShared\**\*.props" />
|
||||||
<Content Remove="..\BarotraumaShared\libsteam_api64.dylib" />
|
<Compile Include="..\BarotraumaShared\**\*.cs" />
|
||||||
<Content Remove="..\BarotraumaShared\libsteam_api64.so" />
|
<Content Remove="..\BarotraumaShared\libsteam_api64.dylib" />
|
||||||
<Content Remove="DedicatedServer.exe" />
|
<Content Remove="..\BarotraumaShared\libsteam_api64.so" />
|
||||||
</ItemGroup>
|
<Content Remove="DedicatedServer.exe" />
|
||||||
|
</ItemGroup>
|
||||||
<ItemGroup Condition="'$(Configuration)'!='Debug'">
|
|
||||||
<ProjectReference Include="..\..\Libraries\Facepunch.Steamworks\Facepunch.Steamworks.Posix.csproj" AdditionalProperties="Configuration=Release" />
|
<ItemGroup Condition="'$(Configuration)'!='Debug'">
|
||||||
<ProjectReference Include="..\..\Libraries\Farseer Physics Engine 3.5\Farseer.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Facepunch.Steamworks\Facepunch.Steamworks.Posix.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
<ProjectReference Include="..\..\Libraries\GameAnalytics\GA_SDK_NETSTANDARD\GA_SDK_NETSTANDARD.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Farseer Physics Engine 3.5\Farseer.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
<ProjectReference Include="..\..\Libraries\Hyper.ComponentModel\Hyper.ComponentModel.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Hyper.ComponentModel\Hyper.ComponentModel.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
<ProjectReference Include="..\..\Libraries\Lidgren.Network\Lidgren.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Lidgren.Network\Lidgren.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Condition="'$(Configuration)'=='Debug'">
|
<ItemGroup Condition="'$(Configuration)'=='Debug'">
|
||||||
<ProjectReference Include="..\..\Libraries\Facepunch.Steamworks\Facepunch.Steamworks.Posix.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Facepunch.Steamworks\Facepunch.Steamworks.Posix.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\Farseer Physics Engine 3.5\Farseer.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Farseer Physics Engine 3.5\Farseer.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\GameAnalytics\GA_SDK_NETSTANDARD\GA_SDK_NETSTANDARD.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Hyper.ComponentModel\Hyper.ComponentModel.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\Hyper.ComponentModel\Hyper.ComponentModel.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Lidgren.Network\Lidgren.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\Lidgren.Network\Lidgren.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
</ItemGroup>
|
||||||
</ItemGroup>
|
|
||||||
|
<ItemGroup>
|
||||||
<!-- Sourced from https://stackoverflow.com/a/45248069 -->
|
<PackageReference Include="RestSharp" Version="106.13.0" />
|
||||||
<ItemGroup>
|
</ItemGroup>
|
||||||
<None Include="..\BarotraumaShared\libsteam_api64.dylib">
|
|
||||||
<Link>libsteam_api64.dylib</Link>
|
<!-- Sourced from https://stackoverflow.com/a/45248069 -->
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<ItemGroup>
|
||||||
</None>
|
<None Include="..\BarotraumaShared\libsteam_api64.dylib">
|
||||||
</ItemGroup>
|
<Link>libsteam_api64.dylib</Link>
|
||||||
<Target Name="GetGitRevision" BeforeTargets="WriteGitRevision" Condition="'$(BuildHash)' == ''">
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
<PropertyGroup>
|
</None>
|
||||||
<!-- temp file for the git version (lives in "obj" folder)-->
|
</ItemGroup>
|
||||||
<VerFile>$(IntermediateOutputPath)gitver</VerFile>
|
<Target Name="GetGitRevision" BeforeTargets="WriteGitRevision" Condition="'$(BuildHash)' == ''">
|
||||||
<BranchFile>$(IntermediateOutputPath)gitbranch</BranchFile>
|
<PropertyGroup>
|
||||||
</PropertyGroup>
|
<!-- temp file for the git version (lives in "obj" folder)-->
|
||||||
|
<VerFile>$(IntermediateOutputPath)gitver</VerFile>
|
||||||
<!-- write the hash to the temp file.-->
|
<BranchFile>$(IntermediateOutputPath)gitbranch</BranchFile>
|
||||||
<Exec Command="git -C $(ProjectDir) rev-parse --short HEAD > $(VerFile)" ContinueOnError="true">
|
</PropertyGroup>
|
||||||
<Output TaskParameter="exitcode" ItemName="exitcodes" />
|
|
||||||
</Exec>
|
<!-- write the hash to the temp file.-->
|
||||||
<Exec Command="git -C $(ProjectDir) rev-parse --short HEAD --symbolic-full-name --abbrev-ref=strict > $(BranchFile)" ContinueOnError="true" />
|
<Exec Command="git -C $(ProjectDir) rev-parse --short HEAD > $(VerFile)" ContinueOnError="true">
|
||||||
|
<Output TaskParameter="exitcode" ItemName="exitcodes" />
|
||||||
<Exec Command="echo GIT_UNAVAILABLE > $(VerFile)" Condition="'%(exitcodes.identity)'>0" />
|
</Exec>
|
||||||
<Exec Command="echo GIT_UNAVAILABLE > $(BranchFile)" Condition="'%(exitcodes.identity)'>0" />
|
<Exec Command="git -C $(ProjectDir) rev-parse --short HEAD --symbolic-full-name --abbrev-ref=strict > $(BranchFile)" ContinueOnError="true" />
|
||||||
|
|
||||||
<!-- read the version into the GitVersion itemGroup-->
|
<Exec Command="echo GIT_UNAVAILABLE > $(VerFile)" Condition="'%(exitcodes.identity)'>0" />
|
||||||
<ReadLinesFromFile File="$(VerFile)">
|
<Exec Command="echo GIT_UNAVAILABLE > $(BranchFile)" Condition="'%(exitcodes.identity)'>0" />
|
||||||
<Output TaskParameter="Lines" ItemName="GitVersion" />
|
|
||||||
</ReadLinesFromFile>
|
<!-- read the version into the GitVersion itemGroup-->
|
||||||
<!-- Set the BuildHash property to contain the GitVersion, if it wasn't already set.-->
|
<ReadLinesFromFile File="$(VerFile)">
|
||||||
<PropertyGroup>
|
<Output TaskParameter="Lines" ItemName="GitVersion" />
|
||||||
<BuildHash>@(GitVersion)</BuildHash>
|
</ReadLinesFromFile>
|
||||||
</PropertyGroup>
|
<!-- Set the BuildHash property to contain the GitVersion, if it wasn't already set.-->
|
||||||
|
<PropertyGroup>
|
||||||
<!-- read the branch into the GitBranch itemGroup-->
|
<BuildHash>@(GitVersion)</BuildHash>
|
||||||
<ReadLinesFromFile File="$(BranchFile)">
|
</PropertyGroup>
|
||||||
<Output TaskParameter="Lines" ItemName="GitBranch" />
|
|
||||||
</ReadLinesFromFile>
|
<!-- read the branch into the GitBranch itemGroup-->
|
||||||
<!-- Set the BuildHash property to contain the GitVersion, if it wasn't already set.-->
|
<ReadLinesFromFile File="$(BranchFile)">
|
||||||
<PropertyGroup>
|
<Output TaskParameter="Lines" ItemName="GitBranch" />
|
||||||
<BuildBranch>@(GitBranch)</BuildBranch>
|
</ReadLinesFromFile>
|
||||||
</PropertyGroup>
|
<!-- Set the BuildHash property to contain the GitVersion, if it wasn't already set.-->
|
||||||
</Target>
|
<PropertyGroup>
|
||||||
|
<BuildBranch>@(GitBranch)</BuildBranch>
|
||||||
<Target Name="WriteGitRevision" BeforeTargets="CoreCompile">
|
</PropertyGroup>
|
||||||
<!-- names the obj/.../CustomAssemblyInfo.cs file -->
|
</Target>
|
||||||
<PropertyGroup>
|
|
||||||
<CustomAssemblyInfoFile>$(IntermediateOutputPath)CustomAssemblyInfo.cs</CustomAssemblyInfoFile>
|
<Target Name="WriteGitRevision" BeforeTargets="CoreCompile">
|
||||||
</PropertyGroup>
|
<!-- names the obj/.../CustomAssemblyInfo.cs file -->
|
||||||
<!-- includes the CustomAssemblyInfo for compilation into your project -->
|
<PropertyGroup>
|
||||||
<ItemGroup>
|
<CustomAssemblyInfoFile>$(IntermediateOutputPath)CustomAssemblyInfo.cs</CustomAssemblyInfoFile>
|
||||||
<Compile Include="$(CustomAssemblyInfoFile)" />
|
</PropertyGroup>
|
||||||
</ItemGroup>
|
<!-- includes the CustomAssemblyInfo for compilation into your project -->
|
||||||
<!-- defines the AssemblyMetadata attribute that will be written -->
|
<ItemGroup>
|
||||||
<ItemGroup>
|
<Compile Include="$(CustomAssemblyInfoFile)" />
|
||||||
<AssemblyAttributes Include="AssemblyMetadata">
|
</ItemGroup>
|
||||||
<_Parameter1>GitRevision</_Parameter1>
|
<!-- defines the AssemblyMetadata attribute that will be written -->
|
||||||
<_Parameter2>$(BuildHash)</_Parameter2>
|
<ItemGroup>
|
||||||
</AssemblyAttributes>
|
<AssemblyAttributes Include="AssemblyMetadata">
|
||||||
<AssemblyAttributes Include="AssemblyMetadata">
|
<_Parameter1>GitRevision</_Parameter1>
|
||||||
<_Parameter1>GitBranch</_Parameter1>
|
<_Parameter2>$(BuildHash)</_Parameter2>
|
||||||
<_Parameter2>$(BuildBranch)</_Parameter2>
|
</AssemblyAttributes>
|
||||||
</AssemblyAttributes>
|
<AssemblyAttributes Include="AssemblyMetadata">
|
||||||
<AssemblyAttributes Include="AssemblyMetadata">
|
<_Parameter1>GitBranch</_Parameter1>
|
||||||
<_Parameter1>ProjectDir</_Parameter1>
|
<_Parameter2>$(BuildBranch)</_Parameter2>
|
||||||
<_Parameter2>$(ProjectDir)</_Parameter2>
|
</AssemblyAttributes>
|
||||||
</AssemblyAttributes>
|
<AssemblyAttributes Include="AssemblyMetadata">
|
||||||
</ItemGroup>
|
<_Parameter1>ProjectDir</_Parameter1>
|
||||||
<!-- writes the attribute to the customAssemblyInfo file -->
|
<_Parameter2>$(ProjectDir)</_Parameter2>
|
||||||
<WriteCodeFragment Language="C#" OutputFile="$(CustomAssemblyInfoFile)" AssemblyAttributes="@(AssemblyAttributes)" />
|
</AssemblyAttributes>
|
||||||
</Target>
|
</ItemGroup>
|
||||||
|
<!-- writes the attribute to the customAssemblyInfo file -->
|
||||||
</Project>
|
<WriteCodeFragment Language="C#" OutputFile="$(CustomAssemblyInfoFile)" AssemblyAttributes="@(AssemblyAttributes)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|||||||
@@ -269,7 +269,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
string errorMsg = "Failed to write input to command line (window width: " + Console.WindowWidth + ", window height: " + Console.WindowHeight + ")\n"
|
string errorMsg = "Failed to write input to command line (window width: " + Console.WindowWidth + ", window height: " + Console.WindowHeight + ")\n"
|
||||||
+ e.Message + "\n" + e.StackTrace.CleanupStackTrace();
|
+ e.Message + "\n" + e.StackTrace.CleanupStackTrace();
|
||||||
GameAnalyticsManager.AddErrorEventOnce("DebugConsole.RewriteInputToCommandLine", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("DebugConsole.RewriteInputToCommandLine", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1588,10 +1588,6 @@ namespace Barotrauma
|
|||||||
if (tpCharacter != null)
|
if (tpCharacter != null)
|
||||||
{
|
{
|
||||||
tpCharacter.TeleportTo(cursorWorldPos);
|
tpCharacter.TeleportTo(cursorWorldPos);
|
||||||
if (tpCharacter.AIController?.SteeringManager is IndoorsSteeringManager pathSteering)
|
|
||||||
{
|
|
||||||
pathSteering.ResetPath();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using Barotrauma.Networking;
|
using Barotrauma.Networking;
|
||||||
using Barotrauma.Steam;
|
using Barotrauma.Steam;
|
||||||
using FarseerPhysics.Dynamics;
|
using FarseerPhysics.Dynamics;
|
||||||
using GameAnalyticsSDK.Net;
|
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -98,8 +97,9 @@ namespace Barotrauma
|
|||||||
|
|
||||||
Console.WriteLine("Initializing SteamManager");
|
Console.WriteLine("Initializing SteamManager");
|
||||||
SteamManager.Initialize();
|
SteamManager.Initialize();
|
||||||
Console.WriteLine("Initializing GameAnalytics");
|
//TODO: figure out how consent is supposed to work for servers
|
||||||
if (GameSettings.SendUserStatistics) GameAnalyticsManager.Init();
|
//Console.WriteLine("Initializing GameAnalytics");
|
||||||
|
//GameAnalyticsManager.InitIfConsented();
|
||||||
|
|
||||||
Console.WriteLine("Initializing GameScreen");
|
Console.WriteLine("Initializing GameScreen");
|
||||||
GameScreen = new GameScreen();
|
GameScreen = new GameScreen();
|
||||||
@@ -418,7 +418,7 @@ namespace Barotrauma
|
|||||||
SaveUtil.CleanUnnecessarySaveFiles();
|
SaveUtil.CleanUnnecessarySaveFiles();
|
||||||
|
|
||||||
if (GameSettings.SaveDebugConsoleLogs || GameSettings.VerboseLogging) { DebugConsole.SaveLogs(); }
|
if (GameSettings.SaveDebugConsoleLogs || GameSettings.VerboseLogging) { DebugConsole.SaveLogs(); }
|
||||||
if (GameSettings.SendUserStatistics) { GameAnalytics.OnQuit(); }
|
if (GameAnalyticsManager.SendUserStatistics) { GameAnalyticsManager.ShutDown(); }
|
||||||
|
|
||||||
MainThread = null;
|
MainThread = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ namespace Barotrauma
|
|||||||
get { return itemData != null; }
|
get { return itemData != null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public CharacterCampaignData(Client client, bool giveRespawnPenaltyAffliction = false)
|
public CharacterCampaignData(Client client)
|
||||||
{
|
{
|
||||||
Name = client.Name;
|
Name = client.Name;
|
||||||
ClientEndPoint = client.Connection.EndPointString;
|
ClientEndPoint = client.Connection.EndPointString;
|
||||||
@@ -22,13 +22,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
healthData = new XElement("health");
|
healthData = new XElement("health");
|
||||||
client.Character?.CharacterHealth?.Save(healthData);
|
client.Character?.CharacterHealth?.Save(healthData);
|
||||||
if (giveRespawnPenaltyAffliction)
|
|
||||||
{
|
|
||||||
var respawnPenaltyAffliction = RespawnManager.GetRespawnPenaltyAffliction();
|
|
||||||
healthData.Add(new XElement("Affliction",
|
|
||||||
new XAttribute("identifier", respawnPenaltyAffliction.Identifier),
|
|
||||||
new XAttribute("strength", respawnPenaltyAffliction.Strength.ToString("G", CultureInfo.InvariantCulture))));
|
|
||||||
}
|
|
||||||
if (client.Character?.Inventory != null)
|
if (client.Character?.Inventory != null)
|
||||||
{
|
{
|
||||||
itemData = new XElement("inventory");
|
itemData = new XElement("inventory");
|
||||||
|
|||||||
@@ -211,18 +211,6 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
c.Character = null;
|
c.Character = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c.HasSpawned && c.CharacterInfo != null && c.CharacterInfo.CauseOfDeath != null && c.CharacterInfo.CauseOfDeath.Type != CauseOfDeathType.Disconnected)
|
|
||||||
{
|
|
||||||
//the client has opted to spawn this round with Reaper's Tax
|
|
||||||
if (c.WaitForNextRoundRespawn.HasValue && !c.WaitForNextRoundRespawn.Value)
|
|
||||||
{
|
|
||||||
c.CharacterInfo.StartItemsGiven = false;
|
|
||||||
characterData.RemoveAll(cd => cd.MatchesClient(c));
|
|
||||||
characterData.Add(new CharacterCampaignData(c, giveRespawnPenaltyAffliction: true));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//use the info of the character the client is currently controlling
|
//use the info of the character the client is currently controlling
|
||||||
// or the previously saved info if not (e.g. if the client has been spectating or died)
|
// or the previously saved info if not (e.g. if the client has been spectating or died)
|
||||||
var characterInfo = c.Character?.Info ?? characterData.Find(d => d.MatchesClient(c))?.CharacterInfo;
|
var characterInfo = c.Character?.Info ?? characterData.Find(d => d.MatchesClient(c))?.CharacterInfo;
|
||||||
@@ -231,6 +219,7 @@ namespace Barotrauma
|
|||||||
if (characterInfo.CauseOfDeath != null && characterInfo.CauseOfDeath.Type != CauseOfDeathType.Disconnected)
|
if (characterInfo.CauseOfDeath != null && characterInfo.CauseOfDeath.Type != CauseOfDeathType.Disconnected)
|
||||||
{
|
{
|
||||||
RespawnManager.ReduceCharacterSkills(characterInfo);
|
RespawnManager.ReduceCharacterSkills(characterInfo);
|
||||||
|
characterInfo.RemoveSavedStatValuesOnDeath();
|
||||||
}
|
}
|
||||||
c.CharacterInfo = characterInfo;
|
c.CharacterInfo = characterInfo;
|
||||||
characterData.RemoveAll(cd => cd.MatchesClient(c));
|
characterData.RemoveAll(cd => cd.MatchesClient(c));
|
||||||
@@ -358,6 +347,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
UpdateCampaignSubs();
|
||||||
|
|
||||||
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
|
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
|
||||||
PendingSubmarineSwitch = null;
|
PendingSubmarineSwitch = null;
|
||||||
@@ -400,20 +390,50 @@ namespace Barotrauma
|
|||||||
|
|
||||||
partial void InitProjSpecific()
|
partial void InitProjSpecific()
|
||||||
{
|
{
|
||||||
if (GameMain.Server != null)
|
CargoManager.OnItemsInBuyCrateChanged += () => { LastUpdateID++; };
|
||||||
{
|
CargoManager.OnPurchasedItemsChanged += () => { LastUpdateID++; };
|
||||||
CargoManager.OnItemsInBuyCrateChanged += () => { LastUpdateID++; };
|
CargoManager.OnSoldItemsChanged += () => { LastUpdateID++; };
|
||||||
CargoManager.OnPurchasedItemsChanged += () => { LastUpdateID++; };
|
UpgradeManager.OnUpgradesChanged += () => { LastUpdateID++; };
|
||||||
CargoManager.OnSoldItemsChanged += () => { LastUpdateID++; };
|
Map.OnLocationSelected += (loc, connection) => { LastUpdateID++; };
|
||||||
UpgradeManager.OnUpgradesChanged += () => { LastUpdateID++; };
|
Map.OnMissionsSelected += (loc, mission) => { LastUpdateID++; };
|
||||||
Map.OnLocationSelected += (loc, connection) => { LastUpdateID++; };
|
Reputation.OnAnyReputationValueChanged += () => { LastUpdateID++; };
|
||||||
Map.OnMissionsSelected += (loc, mission) => { LastUpdateID++; };
|
|
||||||
Reputation.OnAnyReputationValueChanged += () => { LastUpdateID++; };
|
UpdateCampaignSubs();
|
||||||
}
|
|
||||||
//increment save ID so clients know they're lacking the most up-to-date save file
|
//increment save ID so clients know they're lacking the most up-to-date save file
|
||||||
LastSaveID++;
|
LastSaveID++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdateCampaignSubs()
|
||||||
|
{
|
||||||
|
bool isSubmarineVisible(SubmarineInfo s)
|
||||||
|
=> !GameMain.Server.ServerSettings.HiddenSubs.Any(h
|
||||||
|
=> s.Name.Equals(h, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
|
List<SubmarineInfo> availableSubs =
|
||||||
|
SubmarineInfo.SavedSubmarines
|
||||||
|
.Where(s =>
|
||||||
|
s.IsCampaignCompatible
|
||||||
|
&& isSubmarineVisible(s))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (!availableSubs.Any())
|
||||||
|
{
|
||||||
|
//None of the available subs were marked as campaign-compatible, just include all visible subs
|
||||||
|
availableSubs.AddRange(
|
||||||
|
SubmarineInfo.SavedSubmarines
|
||||||
|
.Where(isSubmarineVisible));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!availableSubs.Any())
|
||||||
|
{
|
||||||
|
//No subs are visible at all! Just make the selected one available
|
||||||
|
availableSubs.Add(GameMain.NetLobbyScreen.SelectedSub);
|
||||||
|
}
|
||||||
|
|
||||||
|
GameMain.NetLobbyScreen.CampaignSubmarines = availableSubs;
|
||||||
|
}
|
||||||
|
|
||||||
public void DiscardClientCharacterData(Client client)
|
public void DiscardClientCharacterData(Client client)
|
||||||
{
|
{
|
||||||
characterData.RemoveAll(cd => cd.MatchesClient(client));
|
characterData.RemoveAll(cd => cd.MatchesClient(client));
|
||||||
@@ -1030,14 +1050,6 @@ namespace Barotrauma
|
|||||||
new XAttribute("points", savedExperiencePoint.ExperiencePoints)));
|
new XAttribute("points", savedExperiencePoint.ExperiencePoints)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// save available submarines
|
|
||||||
XElement availableSubsElement = new XElement("AvailableSubs");
|
|
||||||
for (int i = 0; i < GameMain.NetLobbyScreen.CampaignSubmarines.Count; i++)
|
|
||||||
{
|
|
||||||
availableSubsElement.Add(new XElement("Sub", new XAttribute("name", GameMain.NetLobbyScreen.CampaignSubmarines[i].Name)));
|
|
||||||
}
|
|
||||||
modeElement.Add(availableSubsElement);
|
|
||||||
|
|
||||||
element.Add(modeElement);
|
element.Add(modeElement);
|
||||||
|
|
||||||
//save character data to a separate file
|
//save character data to a separate file
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
if (c.Character == null) { return; }
|
if (c.Character == null) { return; }
|
||||||
var requestedFixAction = (FixActions)msg.ReadRangedInteger(0, 2);
|
var requestedFixAction = (FixActions)msg.ReadRangedInteger(0, 2);
|
||||||
|
var QTESuccess = msg.ReadBoolean();
|
||||||
if (requestedFixAction != FixActions.None)
|
if (requestedFixAction != FixActions.None)
|
||||||
{
|
{
|
||||||
if (!c.Character.IsTraitor && requestedFixAction == FixActions.Sabotage)
|
if (!c.Character.IsTraitor && requestedFixAction == FixActions.Sabotage)
|
||||||
@@ -31,6 +32,11 @@ namespace Barotrauma.Items.Components
|
|||||||
item.CreateServerEvent(this);
|
item.CreateServerEvent(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RepairBoost(QTESuccess);
|
||||||
|
item.CreateServerEvent(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null)
|
public void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null)
|
||||||
@@ -42,6 +48,7 @@ namespace Barotrauma.Items.Components
|
|||||||
msg.Write(tinkeringStrength);
|
msg.Write(tinkeringStrength);
|
||||||
msg.Write(CurrentFixer == null ? (ushort)0 : CurrentFixer.ID);
|
msg.Write(CurrentFixer == null ? (ushort)0 : CurrentFixer.ID);
|
||||||
msg.WriteRangedInteger((int)currentFixerAction, 0, 2);
|
msg.WriteRangedInteger((int)currentFixerAction, 0, 2);
|
||||||
|
msg.Write(repairBoost);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
msg.WriteRangedInteger((int)NetEntityEvent.Type.Invalid, 0, Enum.GetValues(typeof(NetEntityEvent.Type)).Length - 1);
|
msg.WriteRangedInteger((int)NetEntityEvent.Type.Invalid, 0, Enum.GetValues(typeof(NetEntityEvent.Type)).Length - 1);
|
||||||
DebugConsole.Log(errorMsg);
|
DebugConsole.Log(errorMsg);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("Item.ServerWrite:InvalidData" + Name, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("Item.ServerWrite:InvalidData" + Name, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,7 +186,7 @@ namespace Barotrauma
|
|||||||
msg.LengthBits = initialWritePos;
|
msg.LengthBits = initialWritePos;
|
||||||
msg.WriteRangedInteger((int)NetEntityEvent.Type.Invalid, 0, Enum.GetValues(typeof(NetEntityEvent.Type)).Length - 1);
|
msg.WriteRangedInteger((int)NetEntityEvent.Type.Invalid, 0, Enum.GetValues(typeof(NetEntityEvent.Type)).Length - 1);
|
||||||
DebugConsole.Log(errorMsg);
|
DebugConsole.Log(errorMsg);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("Item.ServerWrite:" + errorMsg, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("Item.ServerWrite:" + errorMsg, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,7 +402,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
string errorMsg = "Attempted to create a network event for an item (" + Name + ") that hasn't been fully initialized yet.\n" + Environment.StackTrace.CleanupStackTrace();
|
string errorMsg = "Attempted to create a network event for an item (" + Name + ") that hasn't been fully initialized yet.\n" + Environment.StackTrace.CleanupStackTrace();
|
||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("Item.CreateServerEvent:EventForUninitializedItem" + Name + ID, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("Item.CreateServerEvent:EventForUninitializedItem" + Name + ID, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -423,7 +423,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
string errorMsg = "Attempted to create a network event for an item (" + Name + ") that hasn't been fully initialized yet.\n" + Environment.StackTrace.CleanupStackTrace();
|
string errorMsg = "Attempted to create a network event for an item (" + Name + ") that hasn't been fully initialized yet.\n" + Environment.StackTrace.CleanupStackTrace();
|
||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("Item.CreateServerEvent:EventForUninitializedItem" + Name + ID, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("Item.CreateServerEvent:EventForUninitializedItem" + Name + ID, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -274,6 +274,8 @@ namespace Barotrauma.Networking
|
|||||||
public void Save()
|
public void Save()
|
||||||
{
|
{
|
||||||
GameServer.Log("Saving banlist", ServerLog.MessageType.ServerMessage);
|
GameServer.Log("Saving banlist", ServerLog.MessageType.ServerMessage);
|
||||||
|
|
||||||
|
GameMain.Server?.ServerSettings?.UpdateFlag(ServerSettings.NetFlags.Properties);
|
||||||
|
|
||||||
bannedPlayers.RemoveAll(bp => bp.ExpirationTime.HasValue && DateTime.Now > bp.ExpirationTime.Value);
|
bannedPlayers.RemoveAll(bp => bp.ExpirationTime.HasValue && DateTime.Now > bp.ExpirationTime.Value);
|
||||||
|
|
||||||
@@ -344,7 +346,7 @@ namespace Barotrauma.Networking
|
|||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
string errorMsg = "Error while writing banlist. {" + e + "}\n" + e.StackTrace.CleanupStackTrace();
|
string errorMsg = "Error while writing banlist. {" + e + "}\n" + e.StackTrace.CleanupStackTrace();
|
||||||
GameAnalyticsManager.AddErrorEventOnce("Banlist.ServerAdminWrite", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("Banlist.ServerAdminWrite", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -278,7 +278,7 @@ namespace Barotrauma.Networking
|
|||||||
DebugConsole.ThrowError("FileSender threw an exception when trying to send data", e);
|
DebugConsole.ThrowError("FileSender threw an exception when trying to send data", e);
|
||||||
GameAnalyticsManager.AddErrorEventOnce(
|
GameAnalyticsManager.AddErrorEventOnce(
|
||||||
"FileSender.Update:Exception",
|
"FileSender.Update:Exception",
|
||||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
GameAnalyticsManager.ErrorSeverity.Error,
|
||||||
"FileSender threw an exception when trying to send data:\n" + e.Message + "\n" + e.StackTrace.CleanupStackTrace());
|
"FileSender threw an exception when trying to send data:\n" + e.Message + "\n" + e.StackTrace.CleanupStackTrace());
|
||||||
transfer.Status = FileTransferStatus.Error;
|
transfer.Status = FileTransferStatus.Error;
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -600,16 +600,19 @@ namespace Barotrauma.Networking
|
|||||||
//constantly increase AFK timer if the client is controlling a character (gets reset to zero every time an input is received)
|
//constantly increase AFK timer if the client is controlling a character (gets reset to zero every time an input is received)
|
||||||
if (gameStarted && c.Character != null && !c.Character.IsDead && !c.Character.IsIncapacitated)
|
if (gameStarted && c.Character != null && !c.Character.IsDead && !c.Character.IsIncapacitated)
|
||||||
{
|
{
|
||||||
if (c.Connection != OwnerConnection) c.KickAFKTimer += deltaTime;
|
if (c.Connection != OwnerConnection && c.Permissions != ClientPermissions.All) { c.KickAFKTimer += deltaTime; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerable<Client> kickAFK = connectedClients.FindAll(c =>
|
if (connectedClients.Any(c => c.KickAFKTimer >= serverSettings.KickAFKTime))
|
||||||
c.KickAFKTimer >= serverSettings.KickAFKTime &&
|
|
||||||
(OwnerConnection == null || c.Connection != OwnerConnection));
|
|
||||||
foreach (Client c in kickAFK)
|
|
||||||
{
|
{
|
||||||
KickClient(c, "DisconnectMessage.AFK");
|
IEnumerable<Client> kickAFK = connectedClients.FindAll(c =>
|
||||||
|
c.KickAFKTimer >= serverSettings.KickAFKTime &&
|
||||||
|
(OwnerConnection == null || c.Connection != OwnerConnection));
|
||||||
|
foreach (Client c in kickAFK)
|
||||||
|
{
|
||||||
|
KickClient(c, "DisconnectMessage.AFK");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
serverPeer.Update(deltaTime);
|
serverPeer.Update(deltaTime);
|
||||||
@@ -632,7 +635,7 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Failed to write a network message for the client \"" + c.Name + "\"!", e);
|
DebugConsole.ThrowError("Failed to write a network message for the client \"" + c.Name + "\"!", e);
|
||||||
|
|
||||||
string errorMsg = "Failed to write a network message for the client \"" + c.Name + "\"! (MidRoundSyncing: " + c.NeedsMidRoundSync + ")\n"
|
string errorMsg = "Failed to write a network message for a client! (MidRoundSyncing: " + c.NeedsMidRoundSync + ")\n"
|
||||||
+ e.Message + "\n" + e.StackTrace.CleanupStackTrace();
|
+ e.Message + "\n" + e.StackTrace.CleanupStackTrace();
|
||||||
if (e.InnerException != null)
|
if (e.InnerException != null)
|
||||||
{
|
{
|
||||||
@@ -641,7 +644,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
GameAnalyticsManager.AddErrorEventOnce(
|
GameAnalyticsManager.AddErrorEventOnce(
|
||||||
"GameServer.Update:ClientWriteFailed" + e.StackTrace.CleanupStackTrace(),
|
"GameServer.Update:ClientWriteFailed" + e.StackTrace.CleanupStackTrace(),
|
||||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
GameAnalyticsManager.ErrorSeverity.Error,
|
||||||
errorMsg);
|
errorMsg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -791,6 +794,8 @@ namespace Barotrauma.Networking
|
|||||||
string localSavePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Multiplayer, saveName);
|
string localSavePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Multiplayer, saveName);
|
||||||
if (connectedClient.HasPermission(ClientPermissions.SelectMode) || connectedClient.HasPermission(ClientPermissions.ManageCampaign))
|
if (connectedClient.HasPermission(ClientPermissions.SelectMode) || connectedClient.HasPermission(ClientPermissions.ManageCampaign))
|
||||||
{
|
{
|
||||||
|
ServerSettings.RadiationEnabled = settings.RadiationEnabled;
|
||||||
|
ServerSettings.MaxMissionCount = settings.MaxMissionCount;
|
||||||
MultiPlayerCampaign.StartNewCampaign(localSavePath, matchingSub.FilePath, seed, settings);
|
MultiPlayerCampaign.StartNewCampaign(localSavePath, matchingSub.FilePath, seed, settings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -854,6 +859,7 @@ namespace Barotrauma.Networking
|
|||||||
private void HandleClientError(IReadMessage inc, Client c)
|
private void HandleClientError(IReadMessage inc, Client c)
|
||||||
{
|
{
|
||||||
string errorStr = "Unhandled error report";
|
string errorStr = "Unhandled error report";
|
||||||
|
string errorStrNoName = errorStr;
|
||||||
|
|
||||||
ClientNetError error = (ClientNetError)inc.ReadByte();
|
ClientNetError error = (ClientNetError)inc.ReadByte();
|
||||||
switch (error)
|
switch (error)
|
||||||
@@ -861,7 +867,7 @@ namespace Barotrauma.Networking
|
|||||||
case ClientNetError.MISSING_EVENT:
|
case ClientNetError.MISSING_EVENT:
|
||||||
UInt16 expectedID = inc.ReadUInt16();
|
UInt16 expectedID = inc.ReadUInt16();
|
||||||
UInt16 receivedID = inc.ReadUInt16();
|
UInt16 receivedID = inc.ReadUInt16();
|
||||||
errorStr = "Expecting event id " + expectedID.ToString() + ", received " + receivedID.ToString();
|
errorStr = errorStrNoName = "Expecting event id " + expectedID.ToString() + ", received " + receivedID.ToString();
|
||||||
break;
|
break;
|
||||||
case ClientNetError.MISSING_ENTITY:
|
case ClientNetError.MISSING_ENTITY:
|
||||||
UInt16 eventID = inc.ReadUInt16();
|
UInt16 eventID = inc.ReadUInt16();
|
||||||
@@ -869,25 +875,26 @@ namespace Barotrauma.Networking
|
|||||||
Entity entity = Entity.FindEntityByID(entityID);
|
Entity entity = Entity.FindEntityByID(entityID);
|
||||||
if (entity == null)
|
if (entity == null)
|
||||||
{
|
{
|
||||||
errorStr = "Received an update for an entity that doesn't exist (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
|
errorStr = errorStrNoName = "Received an update for an entity that doesn't exist (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
|
||||||
}
|
}
|
||||||
else if (entity is Character character)
|
else if (entity is Character character)
|
||||||
{
|
{
|
||||||
errorStr = "Missing character " + character.Name + " (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
|
errorStr = "Missing character " + character.Name + " (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
|
||||||
|
errorStrNoName = "Missing character " + character.SpeciesName + "(event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
|
||||||
}
|
}
|
||||||
else if (entity is Item item)
|
else if (entity is Item item)
|
||||||
{
|
{
|
||||||
errorStr = "Missing item " + item.Name + " (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
|
errorStr = errorStrNoName = "Missing item " + item.Name + " (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
errorStr = "Missing entity " + entity.ToString() + " (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
|
errorStr = errorStrNoName = "Missing entity " + entity.ToString() + " (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(GameServer.ClientLogName(c) + " has reported an error: " + errorStr, ServerLog.MessageType.Error);
|
Log(ClientLogName(c) + " has reported an error: " + errorStr, ServerLog.MessageType.Error);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.HandleClientError:" + errorStr, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorStr);
|
GameAnalyticsManager.AddErrorEventOnce("GameServer.HandleClientError:" + errorStrNoName, GameAnalyticsManager.ErrorSeverity.Error, errorStr);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -1392,49 +1399,23 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ClientPermissions.SelectSub:
|
case ClientPermissions.SelectSub:
|
||||||
bool isCampaign = inc.ReadBoolean();
|
bool isShuttle = inc.ReadBoolean();
|
||||||
if (!isCampaign)
|
inc.ReadPadBits();
|
||||||
|
UInt16 subIndex = inc.ReadUInt16();
|
||||||
|
var subList = GameMain.NetLobbyScreen.GetSubList();
|
||||||
|
if (subIndex >= subList.Count)
|
||||||
{
|
{
|
||||||
bool isShuttle = inc.ReadBoolean();
|
DebugConsole.NewMessage($"Client \"{ClientLogName(sender)}\" attempted to select a sub, index out of bounds ({subIndex})", Color.Red);
|
||||||
inc.ReadPadBits();
|
|
||||||
UInt16 subIndex = inc.ReadUInt16();
|
|
||||||
var subList = GameMain.NetLobbyScreen.GetSubList();
|
|
||||||
if (subIndex >= subList.Count)
|
|
||||||
{
|
|
||||||
DebugConsole.NewMessage("Client \"" + GameServer.ClientLogName(sender) + "\" attempted to select a sub, index out of bounds (" + subIndex + ")", Color.Red);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (isShuttle)
|
|
||||||
{
|
|
||||||
GameMain.NetLobbyScreen.SelectedShuttle = subList[subIndex];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GameMain.NetLobbyScreen.SelectedSub = subList[subIndex];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int subEqualityCheckVal = inc.ReadInt32();
|
if (isShuttle)
|
||||||
bool add = inc.ReadBoolean();
|
|
||||||
SubmarineInfo sub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.EqualityCheckVal == subEqualityCheckVal);
|
|
||||||
|
|
||||||
if (sub == null)
|
|
||||||
{
|
{
|
||||||
DebugConsole.NewMessage("Client \"" + GameServer.ClientLogName(sender) + "\" attempted to select a sub that does not exist on the server!", Color.Red);
|
GameMain.NetLobbyScreen.SelectedShuttle = subList[subIndex];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (add)
|
GameMain.NetLobbyScreen.SelectedSub = subList[subIndex];
|
||||||
{
|
|
||||||
GameMain.NetLobbyScreen.AddCampaignSubmarine(sub);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GameMain.NetLobbyScreen.RemoveCampaignSubmarine(sub);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1751,7 +1732,7 @@ namespace Barotrauma.Networking
|
|||||||
" Chat message size: " + chatMessageBytes + " bytes\n" +
|
" Chat message size: " + chatMessageBytes + " bytes\n" +
|
||||||
" Position update size: " + positionUpdateBytes + " bytes\n\n";
|
" Position update size: " + positionUpdateBytes + " bytes\n\n";
|
||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.ClientWriteIngame1:PacketSizeExceeded" + outmsg.LengthBytes, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("GameServer.ClientWriteIngame1:PacketSizeExceeded" + outmsg.LengthBytes, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
serverPeer.Send(outmsg, c.Connection, DeliveryMethod.Unreliable);
|
serverPeer.Send(outmsg, c.Connection, DeliveryMethod.Unreliable);
|
||||||
@@ -1791,7 +1772,7 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
|
|
||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.ClientWriteIngame2:PacketSizeExceeded" + outmsg.LengthBytes, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("GameServer.ClientWriteIngame2:PacketSizeExceeded" + outmsg.LengthBytes, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
serverPeer.Send(outmsg, c.Connection, DeliveryMethod.Unreliable);
|
serverPeer.Send(outmsg, c.Connection, DeliveryMethod.Unreliable);
|
||||||
@@ -1878,7 +1859,7 @@ namespace Barotrauma.Networking
|
|||||||
List<int> campaignSubIndices = new List<int>();
|
List<int> campaignSubIndices = new List<int>();
|
||||||
if (GameMain.NetLobbyScreen.SelectedMode == GameModePreset.MultiPlayerCampaign)
|
if (GameMain.NetLobbyScreen.SelectedMode == GameModePreset.MultiPlayerCampaign)
|
||||||
{
|
{
|
||||||
List<SubmarineInfo> subList = GameMain.NetLobbyScreen.GetSubList();
|
IReadOnlyList<SubmarineInfo> subList = GameMain.NetLobbyScreen.GetSubList();
|
||||||
for (int i = 0; i < subList.Count; i++)
|
for (int i = 0; i < subList.Count; i++)
|
||||||
{
|
{
|
||||||
if (GameMain.NetLobbyScreen.CampaignSubmarines.Contains(subList[i]))
|
if (GameMain.NetLobbyScreen.CampaignSubmarines.Contains(subList[i]))
|
||||||
@@ -1916,9 +1897,6 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
outmsg.Write(autoRestartTimerRunning ? serverSettings.AutoRestartTimer : 0.0f);
|
outmsg.Write(autoRestartTimerRunning ? serverSettings.AutoRestartTimer : 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
outmsg.Write(serverSettings.RadiationEnabled);
|
|
||||||
outmsg.Write((byte)serverSettings.MaxMissionCount);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1958,8 +1936,31 @@ namespace Barotrauma.Networking
|
|||||||
chatMessageBytes = outmsg.LengthBytes - outmsg.LengthBytes;
|
chatMessageBytes = outmsg.LengthBytes - outmsg.LengthBytes;
|
||||||
|
|
||||||
outmsg.Write((byte)ServerNetObject.END_OF_MESSAGE);
|
outmsg.Write((byte)ServerNetObject.END_OF_MESSAGE);
|
||||||
|
|
||||||
if (isInitialUpdate)
|
bool messageTooLarge = outmsg.LengthBytes > MsgConstants.MTU;
|
||||||
|
if (messageTooLarge && !isInitialUpdate)
|
||||||
|
{
|
||||||
|
string warningMsg = "Maximum packet size exceeded, will send using reliable mode (" + outmsg.LengthBytes + " > " + MsgConstants.MTU + ")\n";
|
||||||
|
warningMsg +=
|
||||||
|
" Client list size: " + clientListBytes + " bytes\n" +
|
||||||
|
" Chat message size: " + chatMessageBytes + " bytes\n" +
|
||||||
|
" Campaign size: " + campaignBytes + " bytes\n" +
|
||||||
|
" Settings size: " + settingsBytes + " bytes\n";
|
||||||
|
if (initialUpdateBytes > 0)
|
||||||
|
{
|
||||||
|
warningMsg +=
|
||||||
|
" Initial update size: " + settingsBuf.LengthBytes + " bytes\n";
|
||||||
|
}
|
||||||
|
if (settingsBuf != null)
|
||||||
|
{
|
||||||
|
warningMsg +=
|
||||||
|
" Settings buffer size: " + settingsBuf.LengthBytes + " bytes\n";
|
||||||
|
}
|
||||||
|
if (GameSettings.VerboseLogging) { DebugConsole.AddWarning(warningMsg); }
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("GameServer.ClientWriteIngame1:ClientWriteLobby" + outmsg.LengthBytes, GameAnalyticsManager.ErrorSeverity.Warning, warningMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isInitialUpdate || messageTooLarge)
|
||||||
{
|
{
|
||||||
//the initial update may be very large if the host has a large number
|
//the initial update may be very large if the host has a large number
|
||||||
//of submarine files, so the message may have to be fragmented
|
//of submarine files, so the message may have to be fragmented
|
||||||
@@ -1975,28 +1976,6 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (outmsg.LengthBytes > MsgConstants.MTU)
|
|
||||||
{
|
|
||||||
string errorMsg = "Maximum packet size exceeded (" + outmsg.LengthBytes + " > " + MsgConstants.MTU + ")\n";
|
|
||||||
errorMsg +=
|
|
||||||
" Client list size: " + clientListBytes + " bytes\n" +
|
|
||||||
" Chat message size: " + chatMessageBytes + " bytes\n" +
|
|
||||||
" Campaign size: " + campaignBytes + " bytes\n" +
|
|
||||||
" Settings size: " + settingsBytes + " bytes\n";
|
|
||||||
if (initialUpdateBytes > 0)
|
|
||||||
{
|
|
||||||
errorMsg +=
|
|
||||||
" Initial update size: " + settingsBuf.LengthBytes + " bytes\n";
|
|
||||||
}
|
|
||||||
if (settingsBuf != null)
|
|
||||||
{
|
|
||||||
errorMsg +=
|
|
||||||
" Settings buffer size: " + settingsBuf.LengthBytes + " bytes\n";
|
|
||||||
}
|
|
||||||
DebugConsole.ThrowError(errorMsg);
|
|
||||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.ClientWriteIngame1:ClientWriteLobby" + outmsg.LengthBytes, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
serverPeer.Send(outmsg, c.Connection, DeliveryMethod.Unreliable);
|
serverPeer.Send(outmsg, c.Connection, DeliveryMethod.Unreliable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2121,7 +2100,7 @@ namespace Barotrauma.Networking
|
|||||||
startGameCoroutine = null;
|
startGameCoroutine = null;
|
||||||
string errorMsg = "Starting the round failed. Campaign was still active, but the map has been disposed. Try selecting another game mode.";
|
string errorMsg = "Starting the round failed. Campaign was still active, but the map has been disposed. Try selecting another game mode.";
|
||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.StartGame:InvalidCampaignState", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("GameServer.StartGame:InvalidCampaignState", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
if (OwnerConnection != null)
|
if (OwnerConnection != null)
|
||||||
{
|
{
|
||||||
SendDirectChatMessage(errorMsg, connectedClients.Find(c => c.Connection == OwnerConnection), ChatMessageType.Error);
|
SendDirectChatMessage(errorMsg, connectedClients.Find(c => c.Connection == OwnerConnection), ChatMessageType.Error);
|
||||||
@@ -2163,7 +2142,7 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
string errorMsg = "Failed to start a campaign round (next level not set).";
|
string errorMsg = "Failed to start a campaign round (next level not set).";
|
||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.StartGame:InvalidCampaignState", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("GameServer.StartGame:InvalidCampaignState", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
if (OwnerConnection != null)
|
if (OwnerConnection != null)
|
||||||
{
|
{
|
||||||
SendDirectChatMessage(errorMsg, connectedClients.Find(c => c.Connection == OwnerConnection), ChatMessageType.Error);
|
SendDirectChatMessage(errorMsg, connectedClients.Find(c => c.Connection == OwnerConnection), ChatMessageType.Error);
|
||||||
@@ -2392,6 +2371,9 @@ 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]);
|
||||||
|
spawnedCharacter.Info.InventoryData = new XElement("inventory");
|
||||||
|
spawnedCharacter.Info.StartItemsGiven = true;
|
||||||
|
spawnedCharacter.SaveInventory();
|
||||||
// talents are only avilable for players in online sessions, but modders or someone else might want to have them loaded anyway
|
// talents are only avilable for players in online sessions, but modders or someone else might want to have them loaded anyway
|
||||||
spawnedCharacter.LoadTalents();
|
spawnedCharacter.LoadTalents();
|
||||||
}
|
}
|
||||||
@@ -2953,7 +2935,7 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
string errorMsg = "Attempted to send a chat message to a null client.\n" + Environment.StackTrace.CleanupStackTrace();
|
string errorMsg = "Attempted to send a chat message to a null client.\n" + Environment.StackTrace.CleanupStackTrace();
|
||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.SendDirectChatMessage:ClientNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("GameServer.SendDirectChatMessage:ClientNull", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3255,7 +3237,7 @@ namespace Barotrauma.Networking
|
|||||||
BanClient(c, "ServerMessage.KickedByVoteAutoBan", duration: TimeSpan.FromSeconds(serverSettings.AutoBanTime));
|
BanClient(c, "ServerMessage.KickedByVoteAutoBan", duration: TimeSpan.FromSeconds(serverSettings.AutoBanTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
GameMain.NetLobbyScreen.LastUpdateID++;
|
//GameMain.NetLobbyScreen.LastUpdateID++;
|
||||||
|
|
||||||
SendVoteStatus(connectedClients);
|
SendVoteStatus(connectedClients);
|
||||||
|
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ namespace Barotrauma.Networking
|
|||||||
DebugConsole.ThrowError(errorMsg, e);
|
DebugConsole.ThrowError(errorMsg, e);
|
||||||
}
|
}
|
||||||
GameAnalyticsManager.AddErrorEventOnce("ServerEntityEventManager.Read:ReadFailed" + entityName,
|
GameAnalyticsManager.AddErrorEventOnce("ServerEntityEventManager.Read:ReadFailed" + entityName,
|
||||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
GameAnalyticsManager.ErrorSeverity.Error,
|
||||||
"Failed to read server event for entity \"" + entityName + "\"!\n" + e.StackTrace.CleanupStackTrace());
|
"Failed to read server event for entity \"" + entityName + "\"!\n" + e.StackTrace.CleanupStackTrace());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ namespace Barotrauma.Networking
|
|||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
string errorMsg = "Server failed to read an incoming message. {" + e + "}\n" + e.StackTrace.CleanupStackTrace();
|
string errorMsg = "Server failed to read an incoming message. {" + e + "}\n" + e.StackTrace.CleanupStackTrace();
|
||||||
GameAnalyticsManager.AddErrorEventOnce("LidgrenServerPeer.Update:ClientReadException" + e.TargetSite.ToString(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("LidgrenServerPeer.Update:ClientReadException" + e.TargetSite.ToString(), GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg);
|
||||||
#else
|
#else
|
||||||
@@ -208,15 +208,13 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
PendingClient pendingClient = pendingClients.Find(c => (c.Connection is LidgrenConnection l) && l.NetConnection == inc.SenderConnection);
|
PendingClient pendingClient = pendingClients.Find(c => (c.Connection is LidgrenConnection l) && l.NetConnection == inc.SenderConnection);
|
||||||
|
|
||||||
byte incByte = inc.ReadByte();
|
PacketHeader packetHeader = (PacketHeader)inc.ReadByte();
|
||||||
bool isCompressed = (incByte & (byte)PacketHeader.IsCompressed) != 0;
|
|
||||||
bool isConnectionInitializationStep = (incByte & (byte)PacketHeader.IsConnectionInitializationStep) != 0;
|
|
||||||
|
|
||||||
if (isConnectionInitializationStep && pendingClient != null)
|
if (packetHeader.IsConnectionInitializationStep() && pendingClient != null)
|
||||||
{
|
{
|
||||||
ReadConnectionInitializationStep(pendingClient, new ReadWriteMessage(inc.Data, (int)inc.Position, inc.LengthBits, false));
|
ReadConnectionInitializationStep(pendingClient, new ReadWriteMessage(inc.Data, (int)inc.Position, inc.LengthBits, false));
|
||||||
}
|
}
|
||||||
else if (!isConnectionInitializationStep)
|
else if (!packetHeader.IsConnectionInitializationStep())
|
||||||
{
|
{
|
||||||
LidgrenConnection conn = connectedClients.Find(c => (c is LidgrenConnection l) && l.NetConnection == inc.SenderConnection) as LidgrenConnection;
|
LidgrenConnection conn = connectedClients.Find(c => (c is LidgrenConnection l) && l.NetConnection == inc.SenderConnection) as LidgrenConnection;
|
||||||
if (conn == null)
|
if (conn == null)
|
||||||
@@ -242,7 +240,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
//DebugConsole.NewMessage(isCompressed + " " + isConnectionInitializationStep + " " + (int)incByte + " " + length);
|
//DebugConsole.NewMessage(isCompressed + " " + isConnectionInitializationStep + " " + (int)incByte + " " + length);
|
||||||
|
|
||||||
IReadMessage msg = new ReadOnlyMessage(inc.Data, isCompressed, inc.PositionInBytes, length, conn);
|
IReadMessage msg = new ReadOnlyMessage(inc.Data, packetHeader.IsCompressed(), inc.PositionInBytes, length, conn);
|
||||||
OnMessageReceived?.Invoke(conn, msg);
|
OnMessageReceived?.Invoke(conn, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ namespace Barotrauma.Networking
|
|||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
string errorMsg = "Server failed to read an incoming message. {" + e + "}\n" + e.StackTrace.CleanupStackTrace();
|
string errorMsg = "Server failed to read an incoming message. {" + e + "}\n" + e.StackTrace.CleanupStackTrace();
|
||||||
GameAnalyticsManager.AddErrorEventOnce("SteamP2PServerPeer.Update:ClientReadException" + e.TargetSite.ToString(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("SteamP2PServerPeer.Update:ClientReadException" + e.TargetSite.ToString(), GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg);
|
||||||
#else
|
#else
|
||||||
@@ -125,14 +125,9 @@ namespace Barotrauma.Networking
|
|||||||
UInt64 senderSteamId = inc.ReadUInt64();
|
UInt64 senderSteamId = inc.ReadUInt64();
|
||||||
UInt64 ownerSteamId = inc.ReadUInt64();
|
UInt64 ownerSteamId = inc.ReadUInt64();
|
||||||
|
|
||||||
byte incByte = inc.ReadByte();
|
PacketHeader packetHeader = (PacketHeader)inc.ReadByte();
|
||||||
bool isCompressed = (incByte & (byte)PacketHeader.IsCompressed) != 0;
|
|
||||||
bool isConnectionInitializationStep = (incByte & (byte)PacketHeader.IsConnectionInitializationStep) != 0;
|
|
||||||
bool isDisconnectMessage = (incByte & (byte)PacketHeader.IsDisconnectMessage) != 0;
|
|
||||||
bool isServerMessage = (incByte & (byte)PacketHeader.IsServerMessage) != 0;
|
|
||||||
bool isHeartbeatMessage = (incByte & (byte)PacketHeader.IsHeartbeatMessage) != 0;
|
|
||||||
|
|
||||||
if (isServerMessage)
|
if (packetHeader.IsServerMessage())
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Got server message from" + senderSteamId.ToString());
|
DebugConsole.ThrowError("Got server message from" + senderSteamId.ToString());
|
||||||
return;
|
return;
|
||||||
@@ -160,7 +155,7 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (isDisconnectMessage)
|
else if (packetHeader.IsDisconnectMessage())
|
||||||
{
|
{
|
||||||
if (pendingClient != null)
|
if (pendingClient != null)
|
||||||
{
|
{
|
||||||
@@ -174,12 +169,12 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (isHeartbeatMessage)
|
else if (packetHeader.IsHeartbeatMessage())
|
||||||
{
|
{
|
||||||
//message exists solely as a heartbeat, ignore its contents
|
//message exists solely as a heartbeat, ignore its contents
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (isConnectionInitializationStep)
|
else if (packetHeader.IsConnectionInitializationStep())
|
||||||
{
|
{
|
||||||
|
|
||||||
if (pendingClient != null)
|
if (pendingClient != null)
|
||||||
@@ -203,7 +198,7 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
UInt16 length = inc.ReadUInt16();
|
UInt16 length = inc.ReadUInt16();
|
||||||
|
|
||||||
IReadMessage msg = new ReadOnlyMessage(inc.Buffer, isCompressed, inc.BytePosition, length, connectedClient);
|
IReadMessage msg = new ReadOnlyMessage(inc.Buffer, packetHeader.IsCompressed(), inc.BytePosition, length, connectedClient);
|
||||||
OnMessageReceived?.Invoke(connectedClient, msg);
|
OnMessageReceived?.Invoke(connectedClient, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -211,17 +206,17 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
if (OwnerConnection != null) { (OwnerConnection as SteamP2PConnection).Heartbeat(); }
|
if (OwnerConnection != null) { (OwnerConnection as SteamP2PConnection).Heartbeat(); }
|
||||||
|
|
||||||
if (isDisconnectMessage)
|
if (packetHeader.IsDisconnectMessage())
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Received disconnect message from owner");
|
DebugConsole.ThrowError("Received disconnect message from owner");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (isServerMessage)
|
if (packetHeader.IsServerMessage())
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Received server message from owner");
|
DebugConsole.ThrowError("Received server message from owner");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (isConnectionInitializationStep)
|
if (packetHeader.IsConnectionInitializationStep())
|
||||||
{
|
{
|
||||||
if (OwnerConnection == null)
|
if (OwnerConnection == null)
|
||||||
{
|
{
|
||||||
@@ -236,7 +231,7 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (isHeartbeatMessage)
|
if (packetHeader.IsHeartbeatMessage())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -244,7 +239,7 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
UInt16 length = inc.ReadUInt16();
|
UInt16 length = inc.ReadUInt16();
|
||||||
|
|
||||||
IReadMessage msg = new ReadOnlyMessage(inc.Buffer, isCompressed, inc.BytePosition, length, OwnerConnection);
|
IReadMessage msg = new ReadOnlyMessage(inc.Buffer, packetHeader.IsCompressed(), inc.BytePosition, length, OwnerConnection);
|
||||||
OnMessageReceived?.Invoke(OwnerConnection, msg);
|
OnMessageReceived?.Invoke(OwnerConnection, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -267,7 +262,7 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
|
|
||||||
IWriteMessage msgToSend = new WriteOnlyMessage();
|
IWriteMessage msgToSend = new WriteOnlyMessage();
|
||||||
byte[] msgData = new byte[msg.LengthBytes];
|
byte[] msgData = new byte[16];
|
||||||
msg.PrepareForSending(ref msgData, out bool isCompressed, out int length);
|
msg.PrepareForSending(ref msgData, out bool isCompressed, out int length);
|
||||||
msgToSend.Write(conn.SteamID);
|
msgToSend.Write(conn.SteamID);
|
||||||
msgToSend.Write((byte)deliveryMethod);
|
msgToSend.Write((byte)deliveryMethod);
|
||||||
|
|||||||
@@ -398,6 +398,7 @@ namespace Barotrauma.Networking
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
ReduceCharacterSkills(characterInfos[i]);
|
ReduceCharacterSkills(characterInfos[i]);
|
||||||
|
characterInfos[i].RemoveSavedStatValuesOnDeath();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,17 @@ namespace Barotrauma.Networking
|
|||||||
public static readonly string ClientPermissionsFile = "Data" + Path.DirectorySeparatorChar + "clientpermissions.xml";
|
public static readonly string ClientPermissionsFile = "Data" + Path.DirectorySeparatorChar + "clientpermissions.xml";
|
||||||
public static readonly char SubmarineSeparatorChar = '|';
|
public static readonly char SubmarineSeparatorChar = '|';
|
||||||
|
|
||||||
|
public readonly Dictionary<NetFlags, UInt16> LastUpdateIdForFlag = new Dictionary<NetFlags, UInt16>();
|
||||||
|
|
||||||
|
public void UpdateFlag(NetFlags flag)
|
||||||
|
=> LastUpdateIdForFlag[flag] = (UInt16)(GameMain.NetLobbyScreen.LastUpdateID + 1);
|
||||||
|
|
||||||
|
public NetFlags GetRequiredFlags(Client c)
|
||||||
|
=> LastUpdateIdForFlag.Keys
|
||||||
|
.Where(k => LastUpdateIdForFlag[k] > c.LastRecvLobbyUpdate)
|
||||||
|
.Concat(NetFlags.None.ToEnumerable()) //prevents InvalidOperationException in Aggregate
|
||||||
|
.Aggregate((f1, f2) => f1 | f2);
|
||||||
|
|
||||||
partial void InitProjSpecific()
|
partial void InitProjSpecific()
|
||||||
{
|
{
|
||||||
LoadSettings();
|
LoadSettings();
|
||||||
@@ -37,6 +48,9 @@ namespace Barotrauma.Networking
|
|||||||
//outMsg.WritePadBits();
|
//outMsg.WritePadBits();
|
||||||
//outMsg.Write((UInt16)QueryPort);
|
//outMsg.Write((UInt16)QueryPort);
|
||||||
|
|
||||||
|
NetFlags requiredFlags = GetRequiredFlags(c);
|
||||||
|
if (!requiredFlags.HasFlag(NetFlags.Properties)) { return; }
|
||||||
|
|
||||||
WriteNetProperties(outMsg);
|
WriteNetProperties(outMsg);
|
||||||
WriteMonsterEnabled(outMsg);
|
WriteMonsterEnabled(outMsg);
|
||||||
BanList.ServerAdminWrite(outMsg, c);
|
BanList.ServerAdminWrite(outMsg, c);
|
||||||
@@ -45,8 +59,18 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
public void ServerWrite(IWriteMessage outMsg, Client c)
|
public void ServerWrite(IWriteMessage outMsg, Client c)
|
||||||
{
|
{
|
||||||
outMsg.Write(ServerName);
|
NetFlags requiredFlags = GetRequiredFlags(c);
|
||||||
outMsg.Write(ServerMessageText);
|
outMsg.Write((byte)requiredFlags);
|
||||||
|
if (requiredFlags.HasFlag(NetFlags.Name))
|
||||||
|
{
|
||||||
|
outMsg.Write(ServerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requiredFlags.HasFlag(NetFlags.Message))
|
||||||
|
{
|
||||||
|
outMsg.Write(ServerMessageText);
|
||||||
|
}
|
||||||
|
outMsg.Write((byte)PlayStyle);
|
||||||
outMsg.Write((byte)MaxPlayers);
|
outMsg.Write((byte)MaxPlayers);
|
||||||
outMsg.Write(HasPassword);
|
outMsg.Write(HasPassword);
|
||||||
outMsg.Write(IsPublic);
|
outMsg.Write(IsPublic);
|
||||||
@@ -54,12 +78,13 @@ namespace Barotrauma.Networking
|
|||||||
outMsg.WritePadBits();
|
outMsg.WritePadBits();
|
||||||
outMsg.WriteRangedInteger(TickRate, 1, 60);
|
outMsg.WriteRangedInteger(TickRate, 1, 60);
|
||||||
|
|
||||||
WriteExtraCargo(outMsg);
|
if (requiredFlags.HasFlag(NetFlags.Properties))
|
||||||
|
{
|
||||||
|
WriteExtraCargo(outMsg);
|
||||||
|
}
|
||||||
|
|
||||||
WriteHiddenSubs(outMsg);
|
WriteHiddenSubs(outMsg);
|
||||||
|
|
||||||
Voting.ServerWrite(outMsg);
|
|
||||||
|
|
||||||
if (c.HasPermission(Networking.ClientPermissions.ManageSettings))
|
if (c.HasPermission(Networking.ClientPermissions.ManageSettings))
|
||||||
{
|
{
|
||||||
outMsg.Write(true);
|
outMsg.Write(true);
|
||||||
@@ -85,20 +110,20 @@ namespace Barotrauma.Networking
|
|||||||
if (flags.HasFlag(NetFlags.Name))
|
if (flags.HasFlag(NetFlags.Name))
|
||||||
{
|
{
|
||||||
string serverName = incMsg.ReadString();
|
string serverName = incMsg.ReadString();
|
||||||
if (ServerName != serverName) changed = true;
|
if (ServerName != serverName) { changed = true; }
|
||||||
ServerName = serverName;
|
ServerName = serverName;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags.HasFlag(NetFlags.Message))
|
if (flags.HasFlag(NetFlags.Message))
|
||||||
{
|
{
|
||||||
string serverMessageText = incMsg.ReadString();
|
string serverMessageText = incMsg.ReadString();
|
||||||
if (ServerMessageText != serverMessageText) changed = true;
|
if (ServerMessageText != serverMessageText) { changed = true; }
|
||||||
ServerMessageText = serverMessageText;
|
ServerMessageText = serverMessageText;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags.HasFlag(NetFlags.Properties))
|
if (flags.HasFlag(NetFlags.Properties))
|
||||||
{
|
{
|
||||||
changed |= ReadExtraCargo(incMsg);
|
bool propertiesChanged = ReadExtraCargo(incMsg);
|
||||||
|
|
||||||
UInt32 count = incMsg.ReadUInt32();
|
UInt32 count = incMsg.ReadUInt32();
|
||||||
|
|
||||||
@@ -114,7 +139,7 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
GameServer.Log(GameServer.ClientLogName(c) + " changed " + netProperties[key].Name + " to " + netProperties[key].Value.ToString(), ServerLog.MessageType.ServerMessage);
|
GameServer.Log(GameServer.ClientLogName(c) + " changed " + netProperties[key].Name + " to " + netProperties[key].Value.ToString(), ServerLog.MessageType.ServerMessage);
|
||||||
}
|
}
|
||||||
changed = true;
|
propertiesChanged = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -124,10 +149,13 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool changedMonsterSettings = incMsg.ReadBoolean(); incMsg.ReadPadBits();
|
bool changedMonsterSettings = incMsg.ReadBoolean(); incMsg.ReadPadBits();
|
||||||
changed |= changedMonsterSettings;
|
propertiesChanged |= changedMonsterSettings;
|
||||||
if (changedMonsterSettings) ReadMonsterEnabled(incMsg);
|
if (changedMonsterSettings) { ReadMonsterEnabled(incMsg); }
|
||||||
changed |= BanList.ServerAdminRead(incMsg, c);
|
propertiesChanged |= BanList.ServerAdminRead(incMsg, c);
|
||||||
changed |= Whitelist.ServerAdminRead(incMsg, c);
|
propertiesChanged |= Whitelist.ServerAdminRead(incMsg, c);
|
||||||
|
|
||||||
|
if (propertiesChanged) { UpdateFlag(NetFlags.Properties); }
|
||||||
|
changed |= propertiesChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags.HasFlag(NetFlags.HiddenSubs))
|
if (flags.HasFlag(NetFlags.HiddenSubs))
|
||||||
@@ -175,12 +203,14 @@ namespace Barotrauma.Networking
|
|||||||
MaxMissionCount = MathHelper.Clamp(maxMissionCount, CampaignSettings.MinMissionCountLimit, CampaignSettings.MaxMissionCountLimit);
|
MaxMissionCount = MathHelper.Clamp(maxMissionCount, CampaignSettings.MinMissionCountLimit, CampaignSettings.MaxMissionCountLimit);
|
||||||
|
|
||||||
changed |= true;
|
changed |= true;
|
||||||
|
UpdateFlag(NetFlags.Misc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags.HasFlag(NetFlags.LevelSeed))
|
if (flags.HasFlag(NetFlags.LevelSeed))
|
||||||
{
|
{
|
||||||
GameMain.NetLobbyScreen.LevelSeed = incMsg.ReadString();
|
GameMain.NetLobbyScreen.LevelSeed = incMsg.ReadString();
|
||||||
changed |= true;
|
changed |= true;
|
||||||
|
UpdateFlag(NetFlags.LevelSeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
@@ -271,6 +301,8 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
HiddenSubs.UnionWith(doc.Root.GetAttributeStringArray("HiddenSubs", Array.Empty<string>()));
|
HiddenSubs.UnionWith(doc.Root.GetAttributeStringArray("HiddenSubs", Array.Empty<string>()));
|
||||||
|
|
||||||
|
SelectedSubmarine = SelectNonHiddenSubmarine(SelectedSubmarine);
|
||||||
|
|
||||||
string[] defaultAllowedClientNameChars =
|
string[] defaultAllowedClientNameChars =
|
||||||
new string[] {
|
new string[] {
|
||||||
"32-33",
|
"32-33",
|
||||||
@@ -345,7 +377,6 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
GameMain.NetLobbyScreen.SetBotSpawnMode(BotSpawnMode);
|
GameMain.NetLobbyScreen.SetBotSpawnMode(BotSpawnMode);
|
||||||
GameMain.NetLobbyScreen.SetBotCount(BotCount);
|
GameMain.NetLobbyScreen.SetBotCount(BotCount);
|
||||||
GameMain.NetLobbyScreen.SetMaxMissionCount(MaxMissionCount);
|
|
||||||
|
|
||||||
List<string> monsterNames = CharacterPrefab.Prefabs.Select(p => p.Identifier).ToList();
|
List<string> monsterNames = CharacterPrefab.Prefabs.Select(p => p.Identifier).ToList();
|
||||||
MonsterEnabled = new Dictionary<string, bool>();
|
MonsterEnabled = new Dictionary<string, bool>();
|
||||||
@@ -355,16 +386,25 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SelectNonHiddenSubmarine()
|
public string SelectNonHiddenSubmarine(string current = null)
|
||||||
{
|
{
|
||||||
if (HiddenSubs.Contains(GameMain.NetLobbyScreen.SelectedSub.Name))
|
current ??= GameMain.NetLobbyScreen.SelectedSub.Name;
|
||||||
|
if (HiddenSubs.Contains(current))
|
||||||
{
|
{
|
||||||
var candidates = GameMain.NetLobbyScreen.GetSubList().Where(s => !HiddenSubs.Contains(s.Name)).ToArray();
|
var candidates
|
||||||
|
= GameMain.NetLobbyScreen.GetSubList().Where(s => !HiddenSubs.Contains(s.Name)).ToArray();
|
||||||
if (candidates.Any())
|
if (candidates.Any())
|
||||||
{
|
{
|
||||||
GameMain.NetLobbyScreen.SelectedSub = candidates.GetRandom(Rand.RandSync.Unsynced);
|
GameMain.NetLobbyScreen.SelectedSub = candidates.GetRandom(Rand.RandSync.Unsynced);
|
||||||
|
return GameMain.NetLobbyScreen.SelectedSub.Name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HiddenSubs.Remove(current);
|
||||||
|
return current;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadClientPermissions()
|
public void LoadClientPermissions()
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
GameServer.Log("Saving whitelist", ServerLog.MessageType.ServerMessage);
|
GameServer.Log("Saving whitelist", ServerLog.MessageType.ServerMessage);
|
||||||
|
|
||||||
|
GameMain.Server?.ServerSettings?.UpdateFlag(ServerSettings.NetFlags.Properties);
|
||||||
|
|
||||||
List<string> lines = new List<string>();
|
List<string> lines = new List<string>();
|
||||||
|
|
||||||
if (Enabled)
|
if (Enabled)
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
#region Using Statements
|
#region Using Statements
|
||||||
|
|
||||||
using Barotrauma.Steam;
|
using Barotrauma.Steam;
|
||||||
using GameAnalyticsSDK.Net;
|
|
||||||
using System;
|
using System;
|
||||||
using Barotrauma.IO;
|
using Barotrauma.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
#if LINUX
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
#endif
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ namespace Barotrauma
|
|||||||
Game = new GameMain(args);
|
Game = new GameMain(args);
|
||||||
|
|
||||||
Game.Run();
|
Game.Run();
|
||||||
if (GameSettings.SendUserStatistics) { GameAnalytics.OnQuit(); }
|
if (GameAnalyticsManager.SendUserStatistics) { GameAnalyticsManager.ShutDown(); }
|
||||||
SteamManager.ShutDown();
|
SteamManager.ShutDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,6 +152,13 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GameAnalyticsManager.SendUserStatistics)
|
||||||
|
{
|
||||||
|
//send crash report before appending debug console messages (which may contain non-anonymous information)
|
||||||
|
GameAnalyticsManager.AddErrorEvent(GameAnalyticsManager.ErrorSeverity.Critical, sb.ToString());
|
||||||
|
GameAnalyticsManager.ShutDown();
|
||||||
|
}
|
||||||
|
|
||||||
sb.AppendLine("Last debug messages:");
|
sb.AppendLine("Last debug messages:");
|
||||||
DebugConsole.Clear();
|
DebugConsole.Clear();
|
||||||
for (int i = DebugConsole.Messages.Count - 1; i > 0 && i > DebugConsole.Messages.Count - 15; i--)
|
for (int i = DebugConsole.Messages.Count - 1; i > 0 && i > DebugConsole.Messages.Count - 15; i--)
|
||||||
@@ -171,10 +178,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (GameSettings.SaveDebugConsoleLogs || GameSettings.VerboseLogging) { DebugConsole.SaveLogs(); }
|
if (GameSettings.SaveDebugConsoleLogs || GameSettings.VerboseLogging) { DebugConsole.SaveLogs(); }
|
||||||
|
|
||||||
if (GameSettings.SendUserStatistics)
|
if (GameAnalyticsManager.SendUserStatistics)
|
||||||
{
|
{
|
||||||
GameAnalytics.AddErrorEvent(EGAErrorSeverity.Critical, crashReport);
|
|
||||||
GameAnalytics.OnQuit();
|
|
||||||
Console.Write("A crash report (\"servercrashreport.log\") was saved in the root folder of the game and sent to the developers.");
|
Console.Write("A crash report (\"servercrashreport.log\") was saved in the root folder of the game and sent to the developers.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -51,42 +51,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private List<SubmarineInfo> campaignSubmarines;
|
private List<SubmarineInfo> campaignSubmarines;
|
||||||
|
|
||||||
public void AddCampaignSubmarine(SubmarineInfo sub)
|
|
||||||
{
|
|
||||||
if (!campaignSubmarines.Contains(sub))
|
|
||||||
{
|
|
||||||
campaignSubmarines.Add(sub);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lastUpdateID++;
|
|
||||||
if (GameMain.NetworkMember?.ServerSettings != null)
|
|
||||||
{
|
|
||||||
GameMain.NetworkMember.ServerSettings.ServerDetailsChanged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RemoveCampaignSubmarine(SubmarineInfo sub)
|
|
||||||
{
|
|
||||||
if (campaignSubmarines.Contains(sub))
|
|
||||||
{
|
|
||||||
campaignSubmarines.Remove(sub);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lastUpdateID++;
|
|
||||||
if (GameMain.NetworkMember?.ServerSettings != null)
|
|
||||||
{
|
|
||||||
GameMain.NetworkMember.ServerSettings.ServerDetailsChanged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public GameModePreset[] GameModes { get; }
|
public GameModePreset[] GameModes { get; }
|
||||||
|
|
||||||
private int selectedModeIndex;
|
private int selectedModeIndex;
|
||||||
@@ -212,10 +176,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<SubmarineInfo> subs;
|
private List<SubmarineInfo> subs;
|
||||||
public List<SubmarineInfo> GetSubList()
|
public IReadOnlyList<SubmarineInfo> GetSubList() => subs;
|
||||||
{
|
|
||||||
return subs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string LevelSeed
|
public string LevelSeed
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,149 +1,152 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
<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.15.15.0</Version>
|
<Version>0.15.17.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>
|
||||||
<ApplicationIcon>..\BarotraumaShared\Icon.ico</ApplicationIcon>
|
<ApplicationIcon>..\BarotraumaShared\Icon.ico</ApplicationIcon>
|
||||||
<Configurations>Debug;Release;Unstable</Configurations>
|
<Configurations>Debug;Release;Unstable</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
<DefineConstants>DEBUG;TRACE;SERVER;WINDOWS;USE_STEAM</DefineConstants>
|
<DefineConstants>DEBUG;TRACE;SERVER;WINDOWS;USE_STEAM</DefineConstants>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<OutputPath>..\bin\$(Configuration)Windows\</OutputPath>
|
<OutputPath>..\bin\$(Configuration)Windows\</OutputPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<DefineConstants>TRACE;DEBUG;SERVER;WINDOWS;X64;USE_STEAM</DefineConstants>
|
<DefineConstants>TRACE;DEBUG;SERVER;WINDOWS;X64;USE_STEAM</DefineConstants>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<OutputPath>..\bin\$(Configuration)Windows\</OutputPath>
|
<OutputPath>..\bin\$(Configuration)Windows\</OutputPath>
|
||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
<DefineConstants>TRACE;SERVER;WINDOWS;USE_STEAM</DefineConstants>
|
<DefineConstants>TRACE;SERVER;WINDOWS;USE_STEAM</DefineConstants>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<OutputPath>..\bin\$(Configuration)Windows\</OutputPath>
|
<OutputPath>..\bin\$(Configuration)Windows\</OutputPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unstable|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unstable|AnyCPU'">
|
||||||
<DefineConstants>TRACE;SERVER;WINDOWS;USE_STEAM</DefineConstants>
|
<DefineConstants>TRACE;SERVER;WINDOWS;USE_STEAM</DefineConstants>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<OutputPath>..\bin\$(Configuration)Windows\</OutputPath>
|
<OutputPath>..\bin\$(Configuration)Windows\</OutputPath>
|
||||||
<Optimize>true</Optimize>
|
<Optimize>true</Optimize>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<DefineConstants>TRACE;SERVER;WINDOWS;X64;USE_STEAM</DefineConstants>
|
<DefineConstants>TRACE;SERVER;WINDOWS;X64;USE_STEAM</DefineConstants>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<OutputPath>..\bin\$(Configuration)Windows\</OutputPath>
|
<OutputPath>..\bin\$(Configuration)Windows\</OutputPath>
|
||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unstable|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unstable|x64'">
|
||||||
<DefineConstants>TRACE;SERVER;WINDOWS;X64;USE_STEAM</DefineConstants>
|
<DefineConstants>TRACE;SERVER;WINDOWS;X64;USE_STEAM</DefineConstants>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<OutputPath>..\bin\$(Configuration)Windows\</OutputPath>
|
<OutputPath>..\bin\$(Configuration)Windows\</OutputPath>
|
||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
<Optimize>true</Optimize>
|
<Optimize>true</Optimize>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="..\BarotraumaShared\**\*" CopyToOutputDirectory="PreserveNewest" />
|
<Content Include="..\BarotraumaShared\**\*" CopyToOutputDirectory="PreserveNewest" />
|
||||||
<Content Remove="..\BarotraumaShared\**\*.cs" />
|
<Content Remove="..\BarotraumaShared\**\*.cs" />
|
||||||
<Compile Include="..\BarotraumaShared\**\*.cs" />
|
<Content Remove="..\BarotraumaShared\**\*.props" />
|
||||||
<Compile Remove="..\BarotraumaShared\SharedSource\Networking\Primitives\Message\WrapperMsg.cs" />
|
<Compile Include="..\BarotraumaShared\**\*.cs" />
|
||||||
<Content Remove="DedicatedServer.exe" />
|
<Compile Remove="..\BarotraumaShared\SharedSource\Networking\Primitives\Message\WrapperMsg.cs" />
|
||||||
</ItemGroup>
|
<Content Remove="DedicatedServer.exe" />
|
||||||
|
</ItemGroup>
|
||||||
<ItemGroup Condition="'$(Configuration)'!='Debug'">
|
|
||||||
<ProjectReference Include="..\..\Libraries\Facepunch.Steamworks\Facepunch.Steamworks.Win64.csproj" AdditionalProperties="Configuration=Release" />
|
<ItemGroup Condition="'$(Configuration)'!='Debug'">
|
||||||
<ProjectReference Include="..\..\Libraries\Farseer Physics Engine 3.5\Farseer.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Facepunch.Steamworks\Facepunch.Steamworks.Win64.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
<ProjectReference Include="..\..\Libraries\GameAnalytics\GA_SDK_NETSTANDARD\GA_SDK_NETSTANDARD.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Farseer Physics Engine 3.5\Farseer.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
<ProjectReference Include="..\..\Libraries\Hyper.ComponentModel\Hyper.ComponentModel.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Hyper.ComponentModel\Hyper.ComponentModel.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
<ProjectReference Include="..\..\Libraries\Lidgren.Network\Lidgren.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
<ProjectReference Include="..\..\Libraries\Lidgren.Network\Lidgren.NetStandard.csproj" AdditionalProperties="Configuration=Release" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="'$(Configuration)'=='Debug'">
|
<ItemGroup Condition="'$(Configuration)'=='Debug'">
|
||||||
<ProjectReference Include="..\..\Libraries\Facepunch.Steamworks\Facepunch.Steamworks.Win64.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Facepunch.Steamworks\Facepunch.Steamworks.Win64.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\Farseer Physics Engine 3.5\Farseer.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Farseer Physics Engine 3.5\Farseer.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\GameAnalytics\GA_SDK_NETSTANDARD\GA_SDK_NETSTANDARD.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Hyper.ComponentModel\Hyper.ComponentModel.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\Hyper.ComponentModel\Hyper.ComponentModel.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
<ProjectReference Include="..\..\Libraries\Lidgren.Network\Lidgren.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
||||||
<ProjectReference Include="..\..\Libraries\Lidgren.Network\Lidgren.NetStandard.csproj" AdditionalProperties="Configuration=Debug" />
|
</ItemGroup>
|
||||||
</ItemGroup>
|
|
||||||
|
<ItemGroup>
|
||||||
<!-- Sourced from https://stackoverflow.com/a/45248069 -->
|
<PackageReference Include="RestSharp" Version="106.13.0" />
|
||||||
<Target Name="GetGitRevision" BeforeTargets="WriteGitRevision" Condition="'$(BuildHash)' == ''">
|
</ItemGroup>
|
||||||
<PropertyGroup>
|
|
||||||
<!-- temp file for the git version (lives in "obj" folder)-->
|
<!-- Sourced from https://stackoverflow.com/a/45248069 -->
|
||||||
<VerFile>$(IntermediateOutputPath)gitver</VerFile>
|
<Target Name="GetGitRevision" BeforeTargets="WriteGitRevision" Condition="'$(BuildHash)' == ''">
|
||||||
<BranchFile>$(IntermediateOutputPath)gitbranch</BranchFile>
|
<PropertyGroup>
|
||||||
</PropertyGroup>
|
<!-- temp file for the git version (lives in "obj" folder)-->
|
||||||
|
<VerFile>$(IntermediateOutputPath)gitver</VerFile>
|
||||||
<!-- write the hash to the temp file.-->
|
<BranchFile>$(IntermediateOutputPath)gitbranch</BranchFile>
|
||||||
<Exec Command="git -C $(ProjectDir) rev-parse --short HEAD > $(VerFile)" ContinueOnError="true">
|
</PropertyGroup>
|
||||||
<Output TaskParameter="exitcode" ItemName="exitcodes" />
|
|
||||||
</Exec>
|
<!-- write the hash to the temp file.-->
|
||||||
<Exec Command="git -C $(ProjectDir) rev-parse --short HEAD --symbolic-full-name --abbrev-ref=strict > $(BranchFile)" ContinueOnError="true" />
|
<Exec Command="git -C $(ProjectDir) rev-parse --short HEAD > $(VerFile)" ContinueOnError="true">
|
||||||
|
<Output TaskParameter="exitcode" ItemName="exitcodes" />
|
||||||
<Exec Command="echo GIT_UNAVAILABLE > $(VerFile)" Condition="'%(exitcodes.identity)'>0" />
|
</Exec>
|
||||||
<Exec Command="echo GIT_UNAVAILABLE > $(BranchFile)" Condition="'%(exitcodes.identity)'>0" />
|
<Exec Command="git -C $(ProjectDir) rev-parse --short HEAD --symbolic-full-name --abbrev-ref=strict > $(BranchFile)" ContinueOnError="true" />
|
||||||
|
|
||||||
<!-- read the version into the GitVersion itemGroup-->
|
<Exec Command="echo GIT_UNAVAILABLE > $(VerFile)" Condition="'%(exitcodes.identity)'>0" />
|
||||||
<ReadLinesFromFile File="$(VerFile)">
|
<Exec Command="echo GIT_UNAVAILABLE > $(BranchFile)" Condition="'%(exitcodes.identity)'>0" />
|
||||||
<Output TaskParameter="Lines" ItemName="GitVersion" />
|
|
||||||
</ReadLinesFromFile>
|
<!-- read the version into the GitVersion itemGroup-->
|
||||||
<!-- Set the BuildHash property to contain the GitVersion, if it wasn't already set.-->
|
<ReadLinesFromFile File="$(VerFile)">
|
||||||
<PropertyGroup>
|
<Output TaskParameter="Lines" ItemName="GitVersion" />
|
||||||
<BuildHash>@(GitVersion)</BuildHash>
|
</ReadLinesFromFile>
|
||||||
</PropertyGroup>
|
<!-- Set the BuildHash property to contain the GitVersion, if it wasn't already set.-->
|
||||||
|
<PropertyGroup>
|
||||||
<!-- read the branch into the GitBranch itemGroup-->
|
<BuildHash>@(GitVersion)</BuildHash>
|
||||||
<ReadLinesFromFile File="$(BranchFile)">
|
</PropertyGroup>
|
||||||
<Output TaskParameter="Lines" ItemName="GitBranch" />
|
|
||||||
</ReadLinesFromFile>
|
<!-- read the branch into the GitBranch itemGroup-->
|
||||||
<!-- Set the BuildHash property to contain the GitVersion, if it wasn't already set.-->
|
<ReadLinesFromFile File="$(BranchFile)">
|
||||||
<PropertyGroup>
|
<Output TaskParameter="Lines" ItemName="GitBranch" />
|
||||||
<BuildBranch>@(GitBranch)</BuildBranch>
|
</ReadLinesFromFile>
|
||||||
</PropertyGroup>
|
<!-- Set the BuildHash property to contain the GitVersion, if it wasn't already set.-->
|
||||||
</Target>
|
<PropertyGroup>
|
||||||
|
<BuildBranch>@(GitBranch)</BuildBranch>
|
||||||
<Target Name="WriteGitRevision" BeforeTargets="CoreCompile">
|
</PropertyGroup>
|
||||||
<!-- names the obj/.../CustomAssemblyInfo.cs file -->
|
</Target>
|
||||||
<PropertyGroup>
|
|
||||||
<CustomAssemblyInfoFile>$(IntermediateOutputPath)CustomAssemblyInfo.cs</CustomAssemblyInfoFile>
|
<Target Name="WriteGitRevision" BeforeTargets="CoreCompile">
|
||||||
</PropertyGroup>
|
<!-- names the obj/.../CustomAssemblyInfo.cs file -->
|
||||||
<!-- includes the CustomAssemblyInfo for compilation into your project -->
|
<PropertyGroup>
|
||||||
<ItemGroup>
|
<CustomAssemblyInfoFile>$(IntermediateOutputPath)CustomAssemblyInfo.cs</CustomAssemblyInfoFile>
|
||||||
<Compile Include="$(CustomAssemblyInfoFile)" />
|
</PropertyGroup>
|
||||||
</ItemGroup>
|
<!-- includes the CustomAssemblyInfo for compilation into your project -->
|
||||||
<!-- defines the AssemblyMetadata attribute that will be written -->
|
<ItemGroup>
|
||||||
<ItemGroup>
|
<Compile Include="$(CustomAssemblyInfoFile)" />
|
||||||
<AssemblyAttributes Include="AssemblyMetadata">
|
</ItemGroup>
|
||||||
<_Parameter1>GitRevision</_Parameter1>
|
<!-- defines the AssemblyMetadata attribute that will be written -->
|
||||||
<_Parameter2>$(BuildHash)</_Parameter2>
|
<ItemGroup>
|
||||||
</AssemblyAttributes>
|
<AssemblyAttributes Include="AssemblyMetadata">
|
||||||
<AssemblyAttributes Include="AssemblyMetadata">
|
<_Parameter1>GitRevision</_Parameter1>
|
||||||
<_Parameter1>GitBranch</_Parameter1>
|
<_Parameter2>$(BuildHash)</_Parameter2>
|
||||||
<_Parameter2>$(BuildBranch)</_Parameter2>
|
</AssemblyAttributes>
|
||||||
</AssemblyAttributes>
|
<AssemblyAttributes Include="AssemblyMetadata">
|
||||||
<AssemblyAttributes Include="AssemblyMetadata">
|
<_Parameter1>GitBranch</_Parameter1>
|
||||||
<_Parameter1>ProjectDir</_Parameter1>
|
<_Parameter2>$(BuildBranch)</_Parameter2>
|
||||||
<_Parameter2>$(ProjectDir)</_Parameter2>
|
</AssemblyAttributes>
|
||||||
</AssemblyAttributes>
|
<AssemblyAttributes Include="AssemblyMetadata">
|
||||||
</ItemGroup>
|
<_Parameter1>ProjectDir</_Parameter1>
|
||||||
<!-- writes the attribute to the customAssemblyInfo file -->
|
<_Parameter2>$(ProjectDir)</_Parameter2>
|
||||||
<WriteCodeFragment Language="C#" OutputFile="$(CustomAssemblyInfoFile)" AssemblyAttributes="@(AssemblyAttributes)" />
|
</AssemblyAttributes>
|
||||||
</Target>
|
</ItemGroup>
|
||||||
|
<!-- writes the attribute to the customAssemblyInfo file -->
|
||||||
</Project>
|
<WriteCodeFragment Language="C#" OutputFile="$(CustomAssemblyInfoFile)" AssemblyAttributes="@(AssemblyAttributes)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|||||||
@@ -135,6 +135,7 @@
|
|||||||
<Submarine file="Submarines/Kastrull.sub" />
|
<Submarine file="Submarines/Kastrull.sub" />
|
||||||
<Submarine file="Submarines/KastrullDrone.sub" />
|
<Submarine file="Submarines/KastrullDrone.sub" />
|
||||||
<Submarine file="Submarines/Orca.sub" />
|
<Submarine file="Submarines/Orca.sub" />
|
||||||
|
<Submarine file="Submarines/Orca2.sub" />
|
||||||
<Submarine file="Submarines/Remora.sub" />
|
<Submarine file="Submarines/Remora.sub" />
|
||||||
<Submarine file="Submarines/RemoraDrone.sub" />
|
<Submarine file="Submarines/RemoraDrone.sub" />
|
||||||
<Submarine file="Submarines/Selkie.sub" />
|
<Submarine file="Submarines/Selkie.sub" />
|
||||||
|
|||||||
18
Barotrauma/BarotraumaShared/DeployGameAnalytics.props
Normal file
18
Barotrauma/BarotraumaShared/DeployGameAnalytics.props
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<Project>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)'!='Debug'">
|
||||||
|
<IsDebug>false</IsDebug>
|
||||||
|
<IsNotDebug>true</IsNotDebug>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
|
||||||
|
<IsDebug>true</IsDebug>
|
||||||
|
<IsNotDebug>false</IsNotDebug>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Target Name="DeployGameAnalyticsBuild" AfterTargets="CoreCompile" >
|
||||||
|
<Exec Command="dotnet publish $(ProjectDir)../../Libraries/GameAnalytics/GA_SDK_NETSTANDARD/GA_SDK_NETSTANDARD.csproj -c Release -r $(GARuntime) --no-self-contained --nologo -o $(ProjectDir)$(OutputPath)" ContinueOnError="$(IsDebug)" />
|
||||||
|
</Target>
|
||||||
|
<Target Name="DeployGameAnalyticsPublish" AfterTargets="PrepareForPublish" >
|
||||||
|
<Exec Command="dotnet publish $(ProjectDir)../../Libraries/GameAnalytics/GA_SDK_NETSTANDARD/GA_SDK_NETSTANDARD.csproj -c Release -r $(GARuntime) --no-self-contained --nologo -o $(ProjectDir)$(PublishDir)" ContinueOnError="$(IsDebug)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using NLog.Targets;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Barotrauma.Extensions;
|
using Barotrauma.Items.Components;
|
||||||
using Barotrauma.Items.Components;
|
|
||||||
using Barotrauma.Networking;
|
using Barotrauma.Networking;
|
||||||
using FarseerPhysics;
|
using FarseerPhysics;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
@@ -125,6 +124,8 @@ namespace Barotrauma
|
|||||||
minGapSize = ConvertUnits.ToDisplayUnits(Math.Min(colliderWidth, colliderLength));
|
minGapSize = ConvertUnits.ToDisplayUnits(Math.Min(colliderWidth, colliderLength));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual void OnHealed(Character healer, float healAmount) { }
|
||||||
|
|
||||||
public virtual void OnAttacked(Character attacker, AttackResult attackResult) { }
|
public virtual void OnAttacked(Character attacker, AttackResult attackResult) { }
|
||||||
|
|
||||||
public virtual void SelectTarget(AITarget target) { }
|
public virtual void SelectTarget(AITarget target) { }
|
||||||
@@ -306,14 +307,15 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void UnequipEmptyItems(Item parentItem, bool avoidDroppingInSea = true) => UnequipEmptyItems(Character, parentItem, avoidDroppingInSea);
|
public void UnequipEmptyItems(Item parentItem, bool avoidDroppingInSea = true) => UnequipEmptyItems(Character, parentItem, avoidDroppingInSea);
|
||||||
|
|
||||||
public void UnequipContainedItems(Item parentItem, Func<Item, bool> predicate = null, bool avoidDroppingInSea = true) => UnequipContainedItems(Character, parentItem, predicate, avoidDroppingInSea);
|
public void UnequipContainedItems(Item parentItem, Func<Item, bool> predicate = null, bool avoidDroppingInSea = true, int? unequipMax = null) => UnequipContainedItems(Character, parentItem, predicate, avoidDroppingInSea, unequipMax);
|
||||||
|
|
||||||
public static void UnequipEmptyItems(Character character, Item parentItem, bool avoidDroppingInSea = true) => UnequipContainedItems(character, parentItem, it => it.Condition <= 0, avoidDroppingInSea);
|
public static void UnequipEmptyItems(Character character, Item parentItem, bool avoidDroppingInSea = true) => UnequipContainedItems(character, parentItem, it => it.Condition <= 0, avoidDroppingInSea);
|
||||||
|
|
||||||
public static void UnequipContainedItems(Character character, Item parentItem, Func<Item, bool> predicate, bool avoidDroppingInSea = true)
|
public static void UnequipContainedItems(Character character, Item parentItem, Func<Item, bool> predicate, bool avoidDroppingInSea = true, int? unequipMax = null)
|
||||||
{
|
{
|
||||||
var inventory = parentItem.OwnInventory;
|
var inventory = parentItem.OwnInventory;
|
||||||
if (inventory == null) { return; }
|
if (inventory == null) { return; }
|
||||||
|
int removed = 0;
|
||||||
if (predicate == null || inventory.AllItems.Any(predicate))
|
if (predicate == null || inventory.AllItems.Any(predicate))
|
||||||
{
|
{
|
||||||
foreach (Item containedItem in inventory.AllItemsMod)
|
foreach (Item containedItem in inventory.AllItemsMod)
|
||||||
@@ -326,10 +328,12 @@ namespace Barotrauma
|
|||||||
// If we are not inside a friendly sub (= same team), try to put the item in the inventory instead dropping it.
|
// If we are not inside a friendly sub (= same team), try to put the item in the inventory instead dropping it.
|
||||||
if (character.Inventory.TryPutItem(containedItem, character, CharacterInventory.anySlot))
|
if (character.Inventory.TryPutItem(containedItem, character, CharacterInventory.anySlot))
|
||||||
{
|
{
|
||||||
|
if (unequipMax.HasValue && ++removed >= unequipMax) { return; }
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
containedItem.Drop(character);
|
containedItem.Drop(character);
|
||||||
|
if (unequipMax.HasValue && ++removed >= unequipMax) { return; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
string errorMsg = "Invalid AITarget sector direction (" + value + ")\n" + Environment.StackTrace.CleanupStackTrace();
|
string errorMsg = "Invalid AITarget sector direction (" + value + ")\n" + Environment.StackTrace.CleanupStackTrace();
|
||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("AITarget.SectorDir:" + entity?.ToString(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("AITarget.SectorDir:" + entity?.ToString(), GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sectorDir = value;
|
sectorDir = value;
|
||||||
@@ -125,7 +125,7 @@ namespace Barotrauma
|
|||||||
DebugConsole.ThrowError("Attempted to access a removed AITarget\n" + Environment.StackTrace.CleanupStackTrace());
|
DebugConsole.ThrowError("Attempted to access a removed AITarget\n" + Environment.StackTrace.CleanupStackTrace());
|
||||||
#endif
|
#endif
|
||||||
GameAnalyticsManager.AddErrorEventOnce("AITarget.WorldPosition:EntityRemoved",
|
GameAnalyticsManager.AddErrorEventOnce("AITarget.WorldPosition:EntityRemoved",
|
||||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
GameAnalyticsManager.ErrorSeverity.Error,
|
||||||
"Attempted to access a removed AITarget\n" + Environment.StackTrace.CleanupStackTrace());
|
"Attempted to access a removed AITarget\n" + Environment.StackTrace.CleanupStackTrace());
|
||||||
return Vector2.Zero;
|
return Vector2.Zero;
|
||||||
}
|
}
|
||||||
@@ -144,7 +144,7 @@ namespace Barotrauma
|
|||||||
DebugConsole.ThrowError("Attempted to access a removed AITarget\n" + Environment.StackTrace.CleanupStackTrace());
|
DebugConsole.ThrowError("Attempted to access a removed AITarget\n" + Environment.StackTrace.CleanupStackTrace());
|
||||||
#endif
|
#endif
|
||||||
GameAnalyticsManager.AddErrorEventOnce("AITarget.WorldPosition:EntityRemoved",
|
GameAnalyticsManager.AddErrorEventOnce("AITarget.WorldPosition:EntityRemoved",
|
||||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
GameAnalyticsManager.ErrorSeverity.Error,
|
||||||
"Attempted to access a removed AITarget\n" + Environment.StackTrace.CleanupStackTrace());
|
"Attempted to access a removed AITarget\n" + Environment.StackTrace.CleanupStackTrace());
|
||||||
return Vector2.Zero;
|
return Vector2.Zero;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -339,11 +339,15 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
targetingTag = "dead";
|
targetingTag = "dead";
|
||||||
}
|
}
|
||||||
|
else if (AIParams.TryGetTarget(targetCharacter.CharacterHealth.GetActiveAfflictionTags(), out CharacterParams.TargetParams tp) && tp.Threshold > Character.GetDamageDoneByAttacker(targetCharacter))
|
||||||
|
{
|
||||||
|
targetingTag = tp.Tag;
|
||||||
|
}
|
||||||
else if (PetBehavior != null && aiTarget.Entity == PetBehavior.Owner)
|
else if (PetBehavior != null && aiTarget.Entity == PetBehavior.Owner)
|
||||||
{
|
{
|
||||||
targetingTag = "owner";
|
targetingTag = "owner";
|
||||||
}
|
}
|
||||||
else if (AIParams.TryGetTarget(targetCharacter.SpeciesName, out CharacterParams.TargetParams tP))
|
else if (AIParams.TryGetTarget(targetCharacter, out CharacterParams.TargetParams tP))
|
||||||
{
|
{
|
||||||
targetingTag = tP.Tag;
|
targetingTag = tP.Tag;
|
||||||
}
|
}
|
||||||
@@ -353,7 +357,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
targetingTag = "husk";
|
targetingTag = "husk";
|
||||||
}
|
}
|
||||||
else
|
else if (!Character.IsFriendly(targetCharacter))
|
||||||
{
|
{
|
||||||
if (enemy.CombatStrength > CombatStrength)
|
if (enemy.CombatStrength > CombatStrength)
|
||||||
{
|
{
|
||||||
@@ -386,6 +390,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
targetingTag = "sonar";
|
targetingTag = "sonar";
|
||||||
}
|
}
|
||||||
|
if (targetItem.GetComponent<Door>() != null)
|
||||||
|
{
|
||||||
|
targetingTag = "door";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (aiTarget.Entity is Structure)
|
else if (aiTarget.Entity is Structure)
|
||||||
@@ -511,8 +519,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else if (avoidTimer <= 0 || activeTriggers.Any() && returnTimer <= 0)
|
else if (avoidTimer <= 0 || activeTriggers.Any() && returnTimer <= 0)
|
||||||
{
|
{
|
||||||
CharacterParams.TargetParams targetingParams = null;
|
UpdateTargets(out CharacterParams.TargetParams targetingParams);
|
||||||
UpdateTargets(Character, out targetingParams);
|
|
||||||
updateTargetsTimer = updateTargetsInterval * Rand.Range(0.75f, 1.25f);
|
updateTargetsTimer = updateTargetsInterval * Rand.Range(0.75f, 1.25f);
|
||||||
if (SelectedAiTarget == null)
|
if (SelectedAiTarget == null)
|
||||||
{
|
{
|
||||||
@@ -1973,7 +1980,7 @@ namespace Barotrauma
|
|||||||
ChangeTargetState(attacker, canAttack ? AIState.Attack : AIState.Escape, 100);
|
ChangeTargetState(attacker, canAttack ? AIState.Attack : AIState.Escape, 100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (canAttack && attacker.IsHuman && AIParams.TryGetTarget(attacker.SpeciesName, out CharacterParams.TargetParams targetingParams))
|
else if (canAttack && attacker.IsHuman && AIParams.TryGetTarget(attacker, out CharacterParams.TargetParams targetingParams))
|
||||||
{
|
{
|
||||||
if (targetingParams.State == AIState.Aggressive || targetingParams.State == AIState.PassiveAggressive)
|
if (targetingParams.State == AIState.Aggressive || targetingParams.State == AIState.PassiveAggressive)
|
||||||
{
|
{
|
||||||
@@ -2362,7 +2369,7 @@ namespace Barotrauma
|
|||||||
//goes through all the AItargets, evaluates how preferable it is to attack the target,
|
//goes through all the AItargets, evaluates how preferable it is to attack the target,
|
||||||
//whether the Character can see/hear the target and chooses the most preferable target within
|
//whether the Character can see/hear the target and chooses the most preferable target within
|
||||||
//sight/hearing range
|
//sight/hearing range
|
||||||
public AITarget UpdateTargets(Character character, out CharacterParams.TargetParams targetingParams)
|
public AITarget UpdateTargets(out CharacterParams.TargetParams targetingParams)
|
||||||
{
|
{
|
||||||
AITarget newTarget = null;
|
AITarget newTarget = null;
|
||||||
targetValue = 0;
|
targetValue = 0;
|
||||||
@@ -2386,70 +2393,35 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
Character targetCharacter = aiTarget.Entity as Character;
|
Character targetCharacter = aiTarget.Entity as Character;
|
||||||
//ignore the aitarget if it is the Character itself
|
//ignore the aitarget if it is the Character itself
|
||||||
if (targetCharacter == character) { continue; }
|
if (targetCharacter == Character) { continue; }
|
||||||
|
|
||||||
float valueModifier = 1;
|
float valueModifier = 1;
|
||||||
string targetingTag = null;
|
string targetingTag = GetTargetingTag(aiTarget);
|
||||||
if (targetCharacter != null)
|
if (targetCharacter != null)
|
||||||
{
|
{
|
||||||
// ignore if target is tagged to be explicitly ignored (Feign Death)
|
// ignore if target is tagged to be explicitly ignored (Feign Death)
|
||||||
if (targetCharacter.HasAbilityFlag(AbilityFlags.IgnoredByEnemyAI)) { continue; }
|
if (targetCharacter.HasAbilityFlag(AbilityFlags.IgnoredByEnemyAI)) { continue; }
|
||||||
|
if (AIParams.Targets.None() && Character.IsFriendly(targetCharacter))
|
||||||
if (targetCharacter.IsDead)
|
|
||||||
{
|
{
|
||||||
targetingTag = "dead";
|
continue;
|
||||||
}
|
}
|
||||||
else if (PetBehavior != null && aiTarget.Entity == PetBehavior.Owner)
|
if (targetCharacter.AIController is EnemyAIController enemy)
|
||||||
{
|
{
|
||||||
targetingTag = "owner";
|
if (targetingTag == "stronger" && (State == AIState.Avoid || State == AIState.Escape || State == AIState.Flee))
|
||||||
}
|
|
||||||
else if (AIParams.TryGetTarget(targetCharacter.SpeciesName, out CharacterParams.TargetParams tP))
|
|
||||||
{
|
|
||||||
targetingTag = tP.Tag;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (Character.IsFriendly(targetCharacter))
|
|
||||||
{
|
{
|
||||||
continue;
|
if (SelectedAiTarget == aiTarget)
|
||||||
}
|
|
||||||
if (targetCharacter.AIController is EnemyAIController enemy)
|
|
||||||
{
|
|
||||||
if (targetCharacter.IsHusk && AIParams.HasTag("husk"))
|
|
||||||
{
|
{
|
||||||
targetingTag = "husk";
|
// Freightened -> hold on to the target
|
||||||
|
valueModifier *= 2;
|
||||||
}
|
}
|
||||||
else
|
if (IsBeingChasedBy(targetCharacter))
|
||||||
{
|
{
|
||||||
if (enemy.CombatStrength > CombatStrength)
|
valueModifier *= 2;
|
||||||
{
|
}
|
||||||
targetingTag = "stronger";
|
if (Character.CurrentHull != null && !VisibleHulls.Contains(targetCharacter.CurrentHull))
|
||||||
}
|
{
|
||||||
else if (enemy.CombatStrength < CombatStrength)
|
// Inside but in a different room
|
||||||
{
|
valueModifier /= 2;
|
||||||
targetingTag = "weaker";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
targetingTag = "equal";
|
|
||||||
}
|
|
||||||
if (targetingTag == "stronger" && (State == AIState.Avoid || State == AIState.Escape || State == AIState.Flee))
|
|
||||||
{
|
|
||||||
if (SelectedAiTarget == aiTarget)
|
|
||||||
{
|
|
||||||
// Freightened -> hold on to the target
|
|
||||||
valueModifier *= 2;
|
|
||||||
}
|
|
||||||
if (IsBeingChasedBy(targetCharacter))
|
|
||||||
{
|
|
||||||
valueModifier *= 2;
|
|
||||||
}
|
|
||||||
if (Character.CurrentHull != null && !VisibleHulls.Contains(targetCharacter.CurrentHull))
|
|
||||||
{
|
|
||||||
// Inside but in a different room
|
|
||||||
valueModifier /= 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2469,7 +2441,7 @@ namespace Barotrauma
|
|||||||
if (aiTarget.Entity is Hull hull)
|
if (aiTarget.Entity is Hull hull)
|
||||||
{
|
{
|
||||||
// Ignore the target if it's a room and the character is already inside a sub
|
// Ignore the target if it's a room and the character is already inside a sub
|
||||||
if (character.CurrentHull != null) { continue; }
|
if (Character.CurrentHull != null) { continue; }
|
||||||
// Ignore ruins
|
// Ignore ruins
|
||||||
if (hull.Submarine == null) { continue; }
|
if (hull.Submarine == null) { continue; }
|
||||||
if (hull.Submarine.Info.IsRuin) { continue; }
|
if (hull.Submarine.Info.IsRuin) { continue; }
|
||||||
@@ -2479,7 +2451,7 @@ namespace Barotrauma
|
|||||||
if (aiTarget.Entity is Item item)
|
if (aiTarget.Entity is Item item)
|
||||||
{
|
{
|
||||||
door = item.GetComponent<Door>();
|
door = item.GetComponent<Door>();
|
||||||
bool targetingFromOutsideToInside = item.CurrentHull != null && character.CurrentHull == null;
|
bool targetingFromOutsideToInside = item.CurrentHull != null && Character.CurrentHull == null;
|
||||||
if (targetingFromOutsideToInside)
|
if (targetingFromOutsideToInside)
|
||||||
{
|
{
|
||||||
if (door != null && (!canAttackDoors && !AIParams.CanOpenDoors) || !canAttackWalls)
|
if (door != null && (!canAttackDoors && !AIParams.CanOpenDoors) || !canAttackWalls)
|
||||||
@@ -2488,28 +2460,12 @@ namespace Barotrauma
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (var prio in AIParams.Targets)
|
if (door == null && targetingFromOutsideToInside)
|
||||||
{
|
{
|
||||||
if (item.HasTag(prio.Tag))
|
if (item.Submarine?.Info is { IsRuin: true })
|
||||||
{
|
{
|
||||||
targetingTag = prio.Tag;
|
// Ignore ruin items when the creature is outside.
|
||||||
break;
|
continue;
|
||||||
}
|
|
||||||
}
|
|
||||||
if (door == null && targetingTag == null)
|
|
||||||
{
|
|
||||||
if (item.GetComponent<Sonar>() != null)
|
|
||||||
{
|
|
||||||
targetingTag = "sonar";
|
|
||||||
}
|
|
||||||
else if (targetingFromOutsideToInside)
|
|
||||||
{
|
|
||||||
targetingTag = "room";
|
|
||||||
if (item.Submarine?.Info.IsRuin != null)
|
|
||||||
{
|
|
||||||
// Ignore ruin items when the creature is outside.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (targetingTag == "nasonov")
|
else if (targetingTag == "nasonov")
|
||||||
@@ -2521,14 +2477,13 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Ignore the target if it's a decoy and the character is already inside a sub
|
// Ignore the target if it's a decoy and the character is already inside a sub
|
||||||
if (character.CurrentHull != null && targetingTag == "decoy")
|
if (Character.CurrentHull != null && targetingTag == "decoy")
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (aiTarget.Entity is Structure s)
|
else if (aiTarget.Entity is Structure s)
|
||||||
{
|
{
|
||||||
targetingTag = "wall";
|
|
||||||
if (!s.HasBody)
|
if (!s.HasBody)
|
||||||
{
|
{
|
||||||
// Ignore structures that doesn't have a body (not walls)
|
// Ignore structures that doesn't have a body (not walls)
|
||||||
@@ -2537,7 +2492,7 @@ namespace Barotrauma
|
|||||||
if (s.IsPlatform) { continue; }
|
if (s.IsPlatform) { continue; }
|
||||||
if (s.Submarine == null) { continue; }
|
if (s.Submarine == null) { continue; }
|
||||||
if (s.Submarine.Info.IsRuin) { continue; }
|
if (s.Submarine.Info.IsRuin) { continue; }
|
||||||
bool isCharacterInside = character.CurrentHull != null;
|
bool isCharacterInside = Character.CurrentHull != null;
|
||||||
bool isInnerWall = s.prefab.Tags.Contains("inner");
|
bool isInnerWall = s.prefab.Tags.Contains("inner");
|
||||||
if (isInnerWall && !isCharacterInside)
|
if (isInnerWall && !isCharacterInside)
|
||||||
{
|
{
|
||||||
@@ -2624,21 +2579,12 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
targetingTag = "room";
|
|
||||||
}
|
|
||||||
if (door != null)
|
if (door != null)
|
||||||
{
|
{
|
||||||
// If there's not a more specific tag for the door
|
|
||||||
if (string.IsNullOrEmpty(targetingTag) || targetingTag == "room")
|
|
||||||
{
|
|
||||||
targetingTag = "door";
|
|
||||||
}
|
|
||||||
if (door.Item.Submarine == null) { continue; }
|
if (door.Item.Submarine == null) { continue; }
|
||||||
bool isOutdoor = door.LinkedGap?.FlowTargetHull != null && !door.LinkedGap.IsRoomToRoom;
|
bool isOutdoor = door.LinkedGap?.FlowTargetHull != null && !door.LinkedGap.IsRoomToRoom;
|
||||||
// Ignore inner doors when outside
|
// Ignore inner doors when outside
|
||||||
if (character.CurrentHull == null && !isOutdoor) { continue; }
|
if (Character.CurrentHull == null && !isOutdoor) { continue; }
|
||||||
bool isOpen = door.CanBeTraversed;
|
bool isOpen = door.CanBeTraversed;
|
||||||
if (!isOpen)
|
if (!isOpen)
|
||||||
{
|
{
|
||||||
@@ -2651,7 +2597,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
if (IsAggressiveBoarder)
|
if (IsAggressiveBoarder)
|
||||||
{
|
{
|
||||||
if (character.CurrentHull == null)
|
if (Character.CurrentHull == null)
|
||||||
{
|
{
|
||||||
// Increase the priority if the character is outside and the door is from outside to inside
|
// Increase the priority if the character is outside and the door is from outside to inside
|
||||||
if (door.CanBeTraversed)
|
if (door.CanBeTraversed)
|
||||||
@@ -2679,14 +2625,14 @@ namespace Barotrauma
|
|||||||
if (targetingTag == null) { continue; }
|
if (targetingTag == null) { continue; }
|
||||||
var targetParams = GetTargetParams(targetingTag);
|
var targetParams = GetTargetParams(targetingTag);
|
||||||
if (targetParams == null) { continue; }
|
if (targetParams == null) { continue; }
|
||||||
if (targetParams.IgnoreInside && character.CurrentHull != null) { continue; }
|
if (targetParams.IgnoreInside && Character.CurrentHull != null) { continue; }
|
||||||
if (targetParams.IgnoreOutside && character.CurrentHull == null) { continue; }
|
if (targetParams.IgnoreOutside && Character.CurrentHull == null) { continue; }
|
||||||
if (targetParams.IgnoreIncapacitated && targetCharacter != null && targetCharacter.IsIncapacitated) { continue; }
|
if (targetParams.IgnoreIncapacitated && targetCharacter != null && targetCharacter.IsIncapacitated) { continue; }
|
||||||
if (targetParams.IgnoreIfNotInSameSub)
|
if (targetParams.IgnoreIfNotInSameSub)
|
||||||
{
|
{
|
||||||
if (aiTarget.Entity.Submarine != Character.Submarine) { continue; }
|
if (aiTarget.Entity.Submarine != Character.Submarine) { continue; }
|
||||||
var targetHull = targetCharacter != null ? targetCharacter.CurrentHull : aiTarget.Entity is Item it ? it.CurrentHull : null;
|
var targetHull = targetCharacter != null ? targetCharacter.CurrentHull : aiTarget.Entity is Item it ? it.CurrentHull : null;
|
||||||
if ((targetHull == null) != (character.CurrentHull == null)) { continue; }
|
if ((targetHull == null) != (Character.CurrentHull == null)) { continue; }
|
||||||
}
|
}
|
||||||
if (targetParams.State == AIState.Observe || targetParams.State == AIState.Eat)
|
if (targetParams.State == AIState.Observe || targetParams.State == AIState.Eat)
|
||||||
{
|
{
|
||||||
@@ -2706,7 +2652,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
target = selectedTargetingParams == targetParams ? targetParams.ThresholdMax : targetParams.ThresholdMin;
|
target = selectedTargetingParams == targetParams ? targetParams.ThresholdMax : targetParams.ThresholdMin;
|
||||||
}
|
}
|
||||||
if (character.HealthPercentage > target)
|
if (Character.HealthPercentage > target)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -2721,7 +2667,7 @@ namespace Barotrauma
|
|||||||
// Halve the priority for each swarm mate targeting the same target -> reduces stacking
|
// Halve the priority for each swarm mate targeting the same target -> reduces stacking
|
||||||
foreach (Character otherCharacter in SwarmBehavior.Members)
|
foreach (Character otherCharacter in SwarmBehavior.Members)
|
||||||
{
|
{
|
||||||
if (otherCharacter == character) { continue; }
|
if (otherCharacter == Character) { continue; }
|
||||||
if (otherCharacter.AIController?.SelectedAiTarget != aiTarget) { continue; }
|
if (otherCharacter.AIController?.SelectedAiTarget != aiTarget) { continue; }
|
||||||
valueModifier /= 2;
|
valueModifier /= 2;
|
||||||
}
|
}
|
||||||
@@ -2731,15 +2677,15 @@ namespace Barotrauma
|
|||||||
// The same as above, but using all the friendly characters in the level.
|
// The same as above, but using all the friendly characters in the level.
|
||||||
foreach (Character otherCharacter in Character.CharacterList)
|
foreach (Character otherCharacter in Character.CharacterList)
|
||||||
{
|
{
|
||||||
if (otherCharacter == character) { continue; }
|
if (otherCharacter == Character) { continue; }
|
||||||
if (otherCharacter.AIController?.SelectedAiTarget != aiTarget) { continue; }
|
if (otherCharacter.AIController?.SelectedAiTarget != aiTarget) { continue; }
|
||||||
if (!character.IsFriendly(otherCharacter)) { continue; }
|
if (!Character.IsFriendly(otherCharacter)) { continue; }
|
||||||
valueModifier /= 2;
|
valueModifier /= 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!aiTarget.IsWithinSector(WorldPosition)) { continue; }
|
if (!aiTarget.IsWithinSector(WorldPosition)) { continue; }
|
||||||
Vector2 toTarget = aiTarget.WorldPosition - character.WorldPosition;
|
Vector2 toTarget = aiTarget.WorldPosition - Character.WorldPosition;
|
||||||
float dist = toTarget.Length();
|
float dist = toTarget.Length();
|
||||||
float nonModifiedDist = dist;
|
float nonModifiedDist = dist;
|
||||||
//if the target has been within range earlier, the character will notice it more easily
|
//if the target has been within range earlier, the character will notice it more easily
|
||||||
@@ -2829,7 +2775,7 @@ namespace Barotrauma
|
|||||||
Character owner = GetOwner(i);
|
Character owner = GetOwner(i);
|
||||||
// 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 && (Character.IsFriendly(owner) || owner.AiTarget != null && ignoredTargets.Contains(owner.AiTarget)))
|
if (owner != null && (Character.IsFriendly(owner) || owner.AiTarget != null && ignoredTargets.Contains(owner.AiTarget)))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ namespace Barotrauma
|
|||||||
/// List of previous attacks done to this character
|
/// List of previous attacks done to this character
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly Dictionary<Character, AttackResult> previousAttackResults = new Dictionary<Character, AttackResult>();
|
private readonly Dictionary<Character, AttackResult> previousAttackResults = new Dictionary<Character, AttackResult>();
|
||||||
|
private readonly Dictionary<Character, float> previousHealAmounts = new Dictionary<Character, float>();
|
||||||
|
|
||||||
private readonly SteeringManager outsideSteering, insideSteering;
|
private readonly SteeringManager outsideSteering, insideSteering;
|
||||||
|
|
||||||
@@ -187,6 +188,15 @@ namespace Barotrauma
|
|||||||
foreach (var previousAttackResult in previousAttackResults)
|
foreach (var previousAttackResult in previousAttackResults)
|
||||||
{
|
{
|
||||||
RespondToAttack(previousAttackResult.Key, previousAttackResult.Value);
|
RespondToAttack(previousAttackResult.Key, previousAttackResult.Value);
|
||||||
|
if (previousHealAmounts.ContainsKey(previousAttackResult.Key))
|
||||||
|
{
|
||||||
|
//gradually forget past heals
|
||||||
|
previousHealAmounts[previousAttackResult.Key] = Math.Min(previousHealAmounts[previousAttackResult.Key] - 5.0f, 100.0f);
|
||||||
|
if (previousHealAmounts[previousAttackResult.Key] <= 0.0f)
|
||||||
|
{
|
||||||
|
previousHealAmounts.Remove(previousAttackResult.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
previousAttackResults.Clear();
|
previousAttackResults.Clear();
|
||||||
respondToAttackTimer = RespondToAttackInterval;
|
respondToAttackTimer = RespondToAttackInterval;
|
||||||
@@ -237,39 +247,41 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (Character.Submarine == null)
|
if (Character.Submarine == null)
|
||||||
{
|
{
|
||||||
// When the character is outside, far enough from the target, and the direct route is blocked,
|
obstacleRaycastTimer -= deltaTime;
|
||||||
// use the indoor steering with the main and side path waypoints to help avoid getting stuck in level walls
|
if (obstacleRaycastTimer <= 0)
|
||||||
if (SelectedAiTarget?.Entity != null && !IsCloseEnoughToTarget(2000, useTargetSub: false))
|
|
||||||
{
|
{
|
||||||
obstacleRaycastTimer -= deltaTime;
|
obstacleRaycastTimer = obstacleRaycastIntervalLong;
|
||||||
if (obstacleRaycastTimer <= 0)
|
if (SelectedAiTarget?.Entity == null || SelectedAiTarget.Entity is ISpatialEntity target && target.Submarine == null || !IsCloseEnoughToTarget(2000, useTargetSub: false))
|
||||||
{
|
{
|
||||||
obstacleRaycastTimer = obstacleRaycastIntervalLong;
|
// If the target is behind a level wall, switch to the pathing to get around the obstacles.
|
||||||
Vector2 rayEnd = SelectedAiTarget.Entity.SimPosition;
|
ISpatialEntity spatialTarget = SelectedAiTarget?.Entity;
|
||||||
if (SelectedAiTarget.Entity.Submarine != null)
|
if (spatialTarget == null)
|
||||||
{
|
{
|
||||||
rayEnd += SelectedAiTarget.Entity.Submarine.SimPosition;
|
var gotoObjective = ObjectiveManager.GetActiveObjective<AIObjectiveGoTo>();
|
||||||
|
spatialTarget = gotoObjective?.Target;
|
||||||
}
|
}
|
||||||
IEnumerable<FarseerPhysics.Dynamics.Body> ignoredBodies = null;
|
if (spatialTarget == null)
|
||||||
if (SelectedAiTarget.Entity is ISpatialEntity spatialTarget)
|
|
||||||
{
|
{
|
||||||
|
UseIndoorSteeringOutside = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IEnumerable<FarseerPhysics.Dynamics.Body> ignoredBodies = null;
|
||||||
|
Vector2 rayEnd = spatialTarget.SimPosition;
|
||||||
Submarine targetSub = spatialTarget.Submarine;
|
Submarine targetSub = spatialTarget.Submarine;
|
||||||
if (targetSub != null)
|
if (targetSub != null)
|
||||||
{
|
{
|
||||||
|
rayEnd += targetSub.SimPosition;
|
||||||
ignoredBodies = targetSub.PhysicsBody.FarseerBody.ToEnumerable();
|
ignoredBodies = targetSub.PhysicsBody.FarseerBody.ToEnumerable();
|
||||||
}
|
}
|
||||||
|
var obstacle = Submarine.PickBody(SimPosition, rayEnd, ignoredBodies, collisionCategory: Physics.CollisionLevel | Physics.CollisionWall);
|
||||||
|
UseIndoorSteeringOutside = obstacle != null;
|
||||||
}
|
}
|
||||||
var obstacle = Submarine.PickBody(SimPosition, rayEnd, ignoredBodies, collisionCategory: Physics.CollisionLevel | Physics.CollisionWall);
|
|
||||||
UseIndoorSteeringOutside = obstacle != null;
|
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
else
|
|
||||||
{
|
|
||||||
UseIndoorSteeringOutside = false;
|
|
||||||
if (hasValidPath)
|
|
||||||
{
|
{
|
||||||
obstacleRaycastTimer -= deltaTime;
|
UseIndoorSteeringOutside = false;
|
||||||
if (obstacleRaycastTimer <= 0)
|
if (hasValidPath)
|
||||||
{
|
{
|
||||||
obstacleRaycastTimer = obstacleRaycastIntervalShort;
|
obstacleRaycastTimer = obstacleRaycastIntervalShort;
|
||||||
// Swimming outside and using the path finder -> check that the path is not blocked with anything (the path finder doesn't know about other subs).
|
// Swimming outside and using the path finder -> check that the path is not blocked with anything (the path finder doesn't know about other subs).
|
||||||
@@ -332,25 +344,10 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IsInsideCave = Character.CurrentHull == null && Level.Loaded?.Caves.FirstOrDefault(c => c.Area.Contains(Character.WorldPosition)) is Level.Cave;
|
||||||
|
|
||||||
// Check whether the character is inside a cave
|
if (UseIndoorSteeringOutside || Character.CurrentHull?.Submarine != null || hasValidPath || IsCloseEnoughToTarget(steeringBuffer))
|
||||||
if (IsInsideCave)
|
|
||||||
{
|
|
||||||
// If the character was inside a cave, require them to move a bit further from the area to set the field back to false
|
|
||||||
// This is to avoid any twitchy behavior with the steering managers
|
|
||||||
IsInsideCave = Character.CurrentHull == null && Level.Loaded?.Caves.FirstOrDefault(c =>
|
|
||||||
{
|
|
||||||
var area = c.Area;
|
|
||||||
area.Inflate(new Vector2(100));
|
|
||||||
return area.Contains(Character.WorldPosition);
|
|
||||||
}) is Level.Cave;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
IsInsideCave = Character.CurrentHull == null && Level.Loaded?.Caves.FirstOrDefault(c => c.Area.Contains(Character.WorldPosition)) is Level.Cave;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UseIndoorSteeringOutside || IsInsideCave || Character.CurrentHull?.Submarine != null || hasValidPath || IsCloseEnoughToTarget(steeringBuffer))
|
|
||||||
{
|
{
|
||||||
if (steeringManager != insideSteering)
|
if (steeringManager != insideSteering)
|
||||||
{
|
{
|
||||||
@@ -601,7 +598,7 @@ namespace Barotrauma
|
|||||||
takeMaskOff = false;
|
takeMaskOff = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (gotoObjective.mimic)
|
else if (gotoObjective.Mimic)
|
||||||
{
|
{
|
||||||
if (!removeSuit)
|
if (!removeSuit)
|
||||||
{
|
{
|
||||||
@@ -880,7 +877,8 @@ namespace Barotrauma
|
|||||||
if (target.CurrentHull != hull || !target.Enabled) { continue; }
|
if (target.CurrentHull != hull || !target.Enabled) { continue; }
|
||||||
if (AIObjectiveFightIntruders.IsValidTarget(target, Character))
|
if (AIObjectiveFightIntruders.IsValidTarget(target, Character))
|
||||||
{
|
{
|
||||||
if (AddTargets<AIObjectiveFightIntruders, Character>(Character, target) && newOrder == null)
|
bool arrested = AIObjectiveFightIntruders.ShouldArrest(target, Character) && target.HasEquippedItem("handlocker");
|
||||||
|
if (!arrested && AddTargets<AIObjectiveFightIntruders, Character>(Character, target) && newOrder == null)
|
||||||
{
|
{
|
||||||
var orderPrefab = Order.GetPrefab("reportintruders");
|
var orderPrefab = Order.GetPrefab("reportintruders");
|
||||||
newOrder = new Order(orderPrefab, hull, null, orderGiver: Character);
|
newOrder = new Order(orderPrefab, hull, null, orderGiver: Character);
|
||||||
@@ -1033,6 +1031,19 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void OnHealed(Character healer, float healAmount)
|
||||||
|
{
|
||||||
|
if (healer == null || healAmount <= 0.0f) { return; }
|
||||||
|
if (previousHealAmounts.ContainsKey(healer))
|
||||||
|
{
|
||||||
|
previousHealAmounts[healer] += healAmount;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
previousHealAmounts.Add(healer, healAmount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void OnAttacked(Character attacker, AttackResult attackResult)
|
public override void OnAttacked(Character attacker, AttackResult attackResult)
|
||||||
{
|
{
|
||||||
// The attack incapacitated/killed the character: respond immediately to trigger nearby characters because the update loop no longer runs
|
// The attack incapacitated/killed the character: respond immediately to trigger nearby characters because the update loop no longer runs
|
||||||
@@ -1076,11 +1087,16 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void RespondToAttack(Character attacker, AttackResult attackResult)
|
private void RespondToAttack(Character attacker, AttackResult attackResult)
|
||||||
{
|
{
|
||||||
|
float healAmount = 0.0f;
|
||||||
|
if (attacker != null)
|
||||||
|
{
|
||||||
|
previousHealAmounts.TryGetValue(attacker, out healAmount);
|
||||||
|
}
|
||||||
// excluding poisons etc
|
// excluding poisons etc
|
||||||
float realDamage = attackResult.Damage;
|
float realDamage = attackResult.Damage - healAmount;
|
||||||
// including poisons etc
|
// including poisons etc
|
||||||
float totalDamage = realDamage;
|
float totalDamage = realDamage - healAmount;
|
||||||
if (attackResult.Afflictions != null)
|
if (attackResult.Afflictions != null)
|
||||||
{
|
{
|
||||||
foreach (Affliction affliction in attackResult.Afflictions)
|
foreach (Affliction affliction in attackResult.Afflictions)
|
||||||
@@ -1128,7 +1144,7 @@ namespace Barotrauma
|
|||||||
// Should not cancel any existing ai objectives (so that if the character attacked you and then helped, we still would want to retaliate).
|
// Should not cancel any existing ai objectives (so that if the character attacked you and then helped, we still would want to retaliate).
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
float cumulativeDamage = GetDamageDoneByAttacker(attacker);
|
float cumulativeDamage = Character.GetDamageDoneByAttacker(attacker);
|
||||||
bool isAccidental = attacker.IsBot && !IsMentallyUnstable && !attacker.AIController.IsMentallyUnstable && Character.CombatAction == null;
|
bool isAccidental = attacker.IsBot && !IsMentallyUnstable && !attacker.AIController.IsMentallyUnstable && Character.CombatAction == null;
|
||||||
if (isAccidental)
|
if (isAccidental)
|
||||||
{
|
{
|
||||||
@@ -1197,7 +1213,7 @@ namespace Barotrauma
|
|||||||
if (Character.Submarine != null && Character.Submarine.GetConnectedSubs().Contains(attacker.Submarine))
|
if (Character.Submarine != null && Character.Submarine.GetConnectedSubs().Contains(attacker.Submarine))
|
||||||
{
|
{
|
||||||
// Non-friendly
|
// Non-friendly
|
||||||
InformOtherNPCs(GetDamageDoneByAttacker(attacker));
|
InformOtherNPCs(Character.GetDamageDoneByAttacker(attacker));
|
||||||
}
|
}
|
||||||
if (Character.IsBot)
|
if (Character.IsBot)
|
||||||
{
|
{
|
||||||
@@ -1601,21 +1617,19 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ItemTaken(Item item, Character character)
|
public static void ItemTaken(Item item, Character thief)
|
||||||
{
|
{
|
||||||
if (item == null || character == null || item.GetComponent<LevelResource>() != null) { return; }
|
if (item == null || thief == null || item.GetComponent<LevelResource>() != null) { return; }
|
||||||
Character thief = character;
|
|
||||||
bool someoneSpoke = false;
|
|
||||||
|
|
||||||
|
bool someoneSpoke = false;
|
||||||
bool stolenItemsInside = item.OwnInventory?.FindAllItems(it => it.SpawnedInCurrentOutpost && !it.AllowStealing, recursive: true).Any() ?? false;
|
bool stolenItemsInside = item.OwnInventory?.FindAllItems(it => it.SpawnedInCurrentOutpost && !it.AllowStealing, recursive: true).Any() ?? false;
|
||||||
|
|
||||||
if ((item.SpawnedInCurrentOutpost && !item.AllowStealing || stolenItemsInside) && thief.TeamID != CharacterTeamType.FriendlyNPC && !item.HasTag("handlocker"))
|
if ((item.SpawnedInCurrentOutpost && !item.AllowStealing || stolenItemsInside) && thief.TeamID != CharacterTeamType.FriendlyNPC && !item.HasTag("handlocker"))
|
||||||
{
|
{
|
||||||
foreach (Character otherCharacter in Character.CharacterList)
|
foreach (Character otherCharacter in Character.CharacterList)
|
||||||
{
|
{
|
||||||
if (otherCharacter == thief || otherCharacter.TeamID == thief.TeamID || otherCharacter.IsDead ||
|
if (otherCharacter == thief || otherCharacter.TeamID == thief.TeamID || otherCharacter.IsIncapacitated || otherCharacter.Stun > 0.0f ||
|
||||||
otherCharacter.Info?.Job == null ||
|
otherCharacter.Info?.Job == null || !(otherCharacter.AIController is HumanAIController otherHumanAI) ||
|
||||||
!(otherCharacter.AIController is HumanAIController otherHumanAI) ||
|
|
||||||
!otherHumanAI.VisibleHulls.Contains(thief.CurrentHull))
|
!otherHumanAI.VisibleHulls.Contains(thief.CurrentHull))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -1624,13 +1638,13 @@ namespace Barotrauma
|
|||||||
if (!otherCharacter.CanSeeCharacter(thief)) { continue; }
|
if (!otherCharacter.CanSeeCharacter(thief)) { continue; }
|
||||||
// Don't react if the player is taking an extinguisher and there's any fires on the sub, or diving gear when the sub is flooding
|
// Don't react if the player is taking an extinguisher and there's any fires on the sub, or diving gear when the sub is flooding
|
||||||
// -> allow them to use the emergency items
|
// -> allow them to use the emergency items
|
||||||
if (character.Submarine != null)
|
if (thief.Submarine != null)
|
||||||
{
|
{
|
||||||
var connectedHulls = character.Submarine.GetHulls(alsoFromConnectedSubs: true);
|
var connectedHulls = thief.Submarine.GetHulls(alsoFromConnectedSubs: true);
|
||||||
if (item.HasTag("fireextinguisher") && connectedHulls.Any(h => h.FireSources.Any())) { continue; }
|
if (item.HasTag("fireextinguisher") && connectedHulls.Any(h => h.FireSources.Any())) { continue; }
|
||||||
if (item.HasTag("diving") && connectedHulls.Any(h => h.ConnectedGaps.Any(g => AIObjectiveFixLeaks.IsValidTarget(g, thief)))) { continue; }
|
if (item.HasTag("diving") && connectedHulls.Any(h => h.ConnectedGaps.Any(g => AIObjectiveFixLeaks.IsValidTarget(g, thief)))) { continue; }
|
||||||
}
|
}
|
||||||
if (!someoneSpoke && !character.IsIncapacitated && character.Stun <= 0.0f)
|
if (!someoneSpoke)
|
||||||
{
|
{
|
||||||
if (!item.StolenDuringRound && GameMain.GameSession?.Campaign?.Map?.CurrentLocation != null)
|
if (!item.StolenDuringRound && GameMain.GameSession?.Campaign?.Map?.CurrentLocation != null)
|
||||||
{
|
{
|
||||||
@@ -1663,7 +1677,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else if (item.OwnInventory?.FindItem(it => it.SpawnedInCurrentOutpost && !item.AllowStealing, true) is { } foundItem)
|
else if (item.OwnInventory?.FindItem(it => it.SpawnedInCurrentOutpost && !item.AllowStealing, true) is { } foundItem)
|
||||||
{
|
{
|
||||||
ItemTaken(foundItem, character);
|
ItemTaken(foundItem, thief);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TriggerSecurity(HumanAIController humanAI)
|
bool TriggerSecurity(HumanAIController humanAI)
|
||||||
@@ -1791,17 +1805,6 @@ namespace Barotrauma
|
|||||||
humanAI.ObjectiveManager.GetObjective<T1>()?.ReportedTargets.Remove(target));
|
humanAI.ObjectiveManager.GetObjective<T1>()?.ReportedTargets.Remove(target));
|
||||||
}
|
}
|
||||||
|
|
||||||
public float GetDamageDoneByAttacker(Character otherCharacter)
|
|
||||||
{
|
|
||||||
float dmg = 0;
|
|
||||||
Character.Attacker attacker = Character.LastAttackers.LastOrDefault(a => a.Character == otherCharacter);
|
|
||||||
if (attacker != null)
|
|
||||||
{
|
|
||||||
dmg = attacker.Damage;
|
|
||||||
}
|
|
||||||
return dmg;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void StoreHullSafety(Hull hull, HullSafety safety)
|
private void StoreHullSafety(Hull hull, HullSafety safety)
|
||||||
{
|
{
|
||||||
if (knownHulls.ContainsKey(hull))
|
if (knownHulls.ContainsKey(hull))
|
||||||
|
|||||||
@@ -26,10 +26,9 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private float findPathTimer;
|
private float findPathTimer;
|
||||||
|
|
||||||
|
private float checkDoorsTimer;
|
||||||
private float buttonPressCooldown;
|
private float buttonPressCooldown;
|
||||||
|
|
||||||
const float ButtonPressInterval = 0.25f;
|
|
||||||
|
|
||||||
public SteeringPath CurrentPath
|
public SteeringPath CurrentPath
|
||||||
{
|
{
|
||||||
get { return currentPath; }
|
get { return currentPath; }
|
||||||
@@ -97,9 +96,10 @@ namespace Barotrauma
|
|||||||
public override void Update(float speed)
|
public override void Update(float speed)
|
||||||
{
|
{
|
||||||
base.Update(speed);
|
base.Update(speed);
|
||||||
|
float step = 1.0f / 60.0f;
|
||||||
buttonPressCooldown -= 1.0f / 60.0f;
|
checkDoorsTimer -= step;
|
||||||
findPathTimer -= 1.0f / 60.0f;
|
buttonPressCooldown -= step;
|
||||||
|
findPathTimer -= step;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetPath(SteeringPath path)
|
public void SetPath(SteeringPath path)
|
||||||
@@ -204,24 +204,23 @@ namespace Barotrauma
|
|||||||
pathFinder.ApplyPenaltyToOutsideNodes = character.Submarine != null && character.PressureProtection <= 0;
|
pathFinder.ApplyPenaltyToOutsideNodes = character.Submarine != null && character.PressureProtection <= 0;
|
||||||
var newPath = pathFinder.FindPath(currentPos, target, character.Submarine, "(Character: " + character.Name + ")", minGapSize, startNodeFilter, endNodeFilter, nodeFilter, checkVisibility: checkVisibility);
|
var newPath = pathFinder.FindPath(currentPos, target, character.Submarine, "(Character: " + character.Name + ")", minGapSize, startNodeFilter, endNodeFilter, nodeFilter, checkVisibility: checkVisibility);
|
||||||
bool useNewPath = needsNewPath || currentPath == null || currentPath.CurrentNode == null || character.Submarine != null && findPathTimer < -1 && Math.Abs(character.AnimController.TargetMovement.Combine()) <= 0;
|
bool useNewPath = needsNewPath || currentPath == null || currentPath.CurrentNode == null || character.Submarine != null && findPathTimer < -1 && Math.Abs(character.AnimController.TargetMovement.Combine()) <= 0;
|
||||||
if (!useNewPath && currentPath != null && currentPath.CurrentNode != null && newPath.Nodes.Any() && !newPath.Unreachable)
|
if (!useNewPath && currentPath?.CurrentNode != null && newPath.Nodes.Any() && !newPath.Unreachable)
|
||||||
{
|
{
|
||||||
// Check if the new path is the same as the old, in which case we just ignore it and continue using the old path (or the progress would reset).
|
// Check if the new path is the same as the old, in which case we just ignore it and continue using the old path (or the progress would reset).
|
||||||
if (IsIdenticalPath())
|
if (IsIdenticalPath())
|
||||||
{
|
{
|
||||||
useNewPath = false;
|
useNewPath = false;
|
||||||
}
|
}
|
||||||
else
|
else if (!character.IsClimbing)
|
||||||
{
|
{
|
||||||
// Use the new path if it has significantly lower cost (don't change the path if it has marginally smaller cost. This reduces navigating backwards due to new path that is calculated from the node just behind us).
|
// Use the new path if it has significantly lower cost (don't change the path if it has marginally smaller cost. This reduces navigating backwards due to new path that is calculated from the node just behind us).
|
||||||
float t = (float)currentPath.CurrentIndex / (currentPath.Nodes.Count - 1);
|
float t = (float)currentPath.CurrentIndex / (currentPath.Nodes.Count - 1);
|
||||||
useNewPath = newPath.Cost < currentPath.Cost * MathHelper.Lerp(0.95f, 0, t);
|
useNewPath = newPath.Cost < currentPath.Cost * MathHelper.Lerp(0.95f, 0, t);
|
||||||
if (!useNewPath && character.Submarine != null && !character.IsClimbing)
|
if (!useNewPath && character.Submarine != null)
|
||||||
{
|
{
|
||||||
// It's possible that the current path was calculated from a start point that is no longer valid.
|
// It's possible that the current path was calculated from a start point that is no longer valid.
|
||||||
// Therefore, let's accept also paths with a greater cost than the current, if the current node is much farther than the new start node.
|
// Therefore, let's accept also paths with a greater cost than the current, if the current node is much farther than the new start node.
|
||||||
// This is a special case for cases e.g. where the character falls and thus needs a new path.
|
// This is a special case for cases e.g. where the character falls and thus needs a new path.
|
||||||
// Don't do this outside or when climbing ladders, because both cause issues.
|
|
||||||
useNewPath = Vector2.DistanceSquared(character.WorldPosition, currentPath.CurrentNode.WorldPosition) > Math.Pow(Vector2.Distance(character.WorldPosition, newPath.Nodes.First().WorldPosition) * 3, 2);
|
useNewPath = Vector2.DistanceSquared(character.WorldPosition, currentPath.CurrentNode.WorldPosition) > Math.Pow(Vector2.Distance(character.WorldPosition, newPath.Nodes.First().WorldPosition) * 3, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -315,7 +314,8 @@ namespace Barotrauma
|
|||||||
return currentTarget - pos2;
|
return currentTarget - pos2;
|
||||||
}
|
}
|
||||||
bool doorsChecked = false;
|
bool doorsChecked = false;
|
||||||
if (!character.LockHands && buttonPressCooldown <= 0.0f)
|
checkDoorsTimer = Math.Min(checkDoorsTimer, GetDoorCheckTime());
|
||||||
|
if (!character.LockHands && checkDoorsTimer <= 0.0f)
|
||||||
{
|
{
|
||||||
CheckDoorsInPath();
|
CheckDoorsInPath();
|
||||||
doorsChecked = true;
|
doorsChecked = true;
|
||||||
@@ -336,7 +336,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (character.CanInteractWith(ladders.Item))
|
if (character.CanInteractWith(ladders.Item))
|
||||||
{
|
{
|
||||||
ladders.Item.TryInteract(character, false, true);
|
ladders.Item.TryInteract(character, forceSelectKey: true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -347,7 +347,7 @@ namespace Barotrauma
|
|||||||
if (previousLadders != null && previousLadders != ladders && character.SelectedConstruction != previousLadders.Item &&
|
if (previousLadders != null && previousLadders != ladders && character.SelectedConstruction != previousLadders.Item &&
|
||||||
character.CanInteractWith(previousLadders.Item) && Math.Abs(previousLadders.Item.WorldPosition.X - ladders.Item.WorldPosition.X) < 5)
|
character.CanInteractWith(previousLadders.Item) && Math.Abs(previousLadders.Item.WorldPosition.X - ladders.Item.WorldPosition.X) < 5)
|
||||||
{
|
{
|
||||||
previousLadders.Item.TryInteract(character, false, true);
|
previousLadders.Item.TryInteract(character, forceSelectKey: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -387,7 +387,7 @@ namespace Barotrauma
|
|||||||
// Try to change the ladder (hatches between two submarines)
|
// Try to change the ladder (hatches between two submarines)
|
||||||
if (character.SelectedConstruction != nextLadder.Item && nextLadder.Item.IsInsideTrigger(character.WorldPosition))
|
if (character.SelectedConstruction != nextLadder.Item && nextLadder.Item.IsInsideTrigger(character.WorldPosition))
|
||||||
{
|
{
|
||||||
nextLadder.Item.TryInteract(character, false, true);
|
nextLadder.Item.TryInteract(character, forceSelectKey: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isAboveFloor || nextLadderSameAsCurrent)
|
if (isAboveFloor || nextLadderSameAsCurrent)
|
||||||
@@ -487,7 +487,14 @@ namespace Barotrauma
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// We'll want this to run each time, because the delegate is used to find a valid button component.
|
// We'll want this to run each time, because the delegate is used to find a valid button component.
|
||||||
bool canAccessButtons = door.Item.GetConnectedComponents<Controller>(true).Any(b => b.HasAccess(character) && (buttonFilter == null || buttonFilter(b)));
|
bool canAccessButtons = false;
|
||||||
|
foreach (var button in door.Item.GetConnectedComponents<Controller>(true))
|
||||||
|
{
|
||||||
|
if (button.HasAccess(character) && (buttonFilter == null || buttonFilter(button)))
|
||||||
|
{
|
||||||
|
canAccessButtons = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
return canAccessButtons || door.IsOpen || ShouldBreakDoor(door);
|
return canAccessButtons || door.IsOpen || ShouldBreakDoor(door);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -500,8 +507,22 @@ namespace Barotrauma
|
|||||||
return ConvertUnits.ToDisplayUnits(Math.Max(colliderSize.X, colliderSize.Y));
|
return ConvertUnits.ToDisplayUnits(Math.Max(colliderSize.X, colliderSize.Y));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private (Door door, bool state) lastDoor;
|
||||||
|
private float GetDoorCheckTime()
|
||||||
|
{
|
||||||
|
if (steering.LengthSquared() > 0)
|
||||||
|
{
|
||||||
|
return character.AnimController.IsMovingFast ? 0.1f : 0.3f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return float.PositiveInfinity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void CheckDoorsInPath()
|
private void CheckDoorsInPath()
|
||||||
{
|
{
|
||||||
|
checkDoorsTimer = GetDoorCheckTime();
|
||||||
if (!canOpenDoors) { return; }
|
if (!canOpenDoors) { return; }
|
||||||
for (int i = 0; i < 5; i++)
|
for (int i = 0; i < 5; i++)
|
||||||
{
|
{
|
||||||
@@ -518,8 +539,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool closeDoors = character.IsBot && character.IsInFriendlySub || character.Params.AI != null && character.Params.AI.KeepDoorsClosed;
|
if (i == 0)
|
||||||
if (i == 0 || !closeDoors)
|
|
||||||
{
|
{
|
||||||
currentWaypoint = currentPath.CurrentNode;
|
currentWaypoint = currentPath.CurrentNode;
|
||||||
nextWaypoint = currentPath.NextNode;
|
nextWaypoint = currentPath.NextNode;
|
||||||
@@ -540,7 +560,7 @@ namespace Barotrauma
|
|||||||
if (currentWaypoint.ConnectedDoor.LinkedGap != null)
|
if (currentWaypoint.ConnectedDoor.LinkedGap != null)
|
||||||
{
|
{
|
||||||
// Keep the airlock doors closed, but not in ruins/wrecks
|
// Keep the airlock doors closed, but not in ruins/wrecks
|
||||||
if (currentWaypoint.ConnectedDoor.LinkedGap.IsRoomToRoom || currentWaypoint.Submarine?.Info.IsRuin != null || currentWaypoint.Submarine?.Info.IsWreck != null)
|
if (currentWaypoint.ConnectedDoor.LinkedGap.IsRoomToRoom && currentWaypoint.CurrentHull is { IsWetRoom: false } || currentWaypoint.Submarine == null || currentWaypoint.Submarine.Info.IsRuin || currentWaypoint.Submarine.Info.IsWreck)
|
||||||
{
|
{
|
||||||
shouldBeOpen = true;
|
shouldBeOpen = true;
|
||||||
door = currentWaypoint.ConnectedDoor;
|
door = currentWaypoint.ConnectedDoor;
|
||||||
@@ -566,28 +586,49 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (door == null) { return; }
|
if (door == null) { return; }
|
||||||
|
|
||||||
|
if (door.BotsShouldKeepOpen) { shouldBeOpen = true; }
|
||||||
|
|
||||||
//toggle the door if it's the previous node and open, or if it's current node and closed
|
|
||||||
if ((door.IsOpen || door.IsBroken) != shouldBeOpen)
|
if ((door.IsOpen || door.IsBroken) != shouldBeOpen)
|
||||||
{
|
{
|
||||||
|
if (!shouldBeOpen)
|
||||||
|
{
|
||||||
|
if (character.AIController is HumanAIController humanAI)
|
||||||
|
{
|
||||||
|
bool keepDoorsClosed = character.IsBot && door.Item.Submarine?.TeamID == character.TeamID || character.Params.AI != null && character.Params.AI.KeepDoorsClosed;
|
||||||
|
if (!keepDoorsClosed) { return; }
|
||||||
|
bool isInAirlock = door.Item.CurrentHull is { IsWetRoom: true } || character.CurrentHull is { IsWetRoom: true };
|
||||||
|
if (!isInAirlock)
|
||||||
|
{
|
||||||
|
// Don't slam the door at anyones face
|
||||||
|
if (Character.CharacterList.Any(c => c != character && humanAI.IsFriendly(c) && humanAI.VisibleHulls.Contains(c.CurrentHull) && !c.IsUnconscious))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Controller closestButton = null;
|
Controller closestButton = null;
|
||||||
float closestDist = 0;
|
float closestDist = 0;
|
||||||
bool canAccess = CanAccessDoor(door, button =>
|
bool canAccess = CanAccessDoor(door, button =>
|
||||||
{
|
{
|
||||||
if (currentWaypoint == null) { return true; }
|
if (currentWaypoint == null) { return true; }
|
||||||
// Check that the button is on the right side of the door.
|
// Check that the button is on the right side of the door. If the door is open, doesn't matter
|
||||||
if (door.LinkedGap.IsHorizontal)
|
if (!door.IsOpen)
|
||||||
{
|
{
|
||||||
int dir = Math.Sign((nextWaypoint ?? currentWaypoint).WorldPosition.X - door.Item.WorldPosition.X);
|
if (door.LinkedGap.IsHorizontal)
|
||||||
if (button.Item.WorldPosition.X * dir > door.Item.WorldPosition.X * dir) { return false; }
|
{
|
||||||
}
|
int dir = Math.Sign((nextWaypoint ?? currentWaypoint).WorldPosition.X - door.Item.WorldPosition.X);
|
||||||
else
|
if (button.Item.WorldPosition.X * dir > door.Item.WorldPosition.X * dir) { return false; }
|
||||||
{
|
}
|
||||||
int dir = Math.Sign((nextWaypoint ?? currentWaypoint).WorldPosition.Y - door.Item.WorldPosition.Y);
|
else
|
||||||
if (button.Item.WorldPosition.Y * dir > door.Item.WorldPosition.Y * dir) { return false; }
|
{
|
||||||
|
int dir = Math.Sign((nextWaypoint ?? currentWaypoint).WorldPosition.Y - door.Item.WorldPosition.Y);
|
||||||
|
if (button.Item.WorldPosition.Y * dir > door.Item.WorldPosition.Y * dir) { return false; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
float distance = Vector2.DistanceSquared(button.Item.WorldPosition, character.WorldPosition);
|
float distance = Vector2.DistanceSquared(button.Item.WorldPosition, character.WorldPosition);
|
||||||
if (closestButton == null || distance < closestDist)
|
if (closestButton == null || distance < closestDist && character.CanSeeTarget(button.Item))
|
||||||
{
|
{
|
||||||
closestButton = button;
|
closestButton = button;
|
||||||
closestDist = distance;
|
closestDist = distance;
|
||||||
@@ -596,18 +637,39 @@ namespace Barotrauma
|
|||||||
});
|
});
|
||||||
if (canAccess)
|
if (canAccess)
|
||||||
{
|
{
|
||||||
|
bool pressButton = buttonPressCooldown <= 0 || lastDoor.door != door || lastDoor.state != shouldBeOpen;
|
||||||
if (door.HasIntegratedButtons)
|
if (door.HasIntegratedButtons)
|
||||||
{
|
{
|
||||||
door.Item.TryInteract(character, false, true);
|
if (pressButton && character.CanSeeTarget(door.Item))
|
||||||
buttonPressCooldown = ButtonPressInterval;
|
{
|
||||||
|
if (door.Item.TryInteract(character, forceSelectKey: true))
|
||||||
|
{
|
||||||
|
lastDoor = (door, shouldBeOpen);
|
||||||
|
buttonPressCooldown = 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buttonPressCooldown = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (closestButton != null)
|
else if (closestButton != null)
|
||||||
{
|
{
|
||||||
if (Vector2.DistanceSquared(closestButton.Item.WorldPosition, character.WorldPosition) < MathUtils.Pow(closestButton.Item.InteractDistance + GetColliderLength(), 2))
|
if (closestDist < MathUtils.Pow2(closestButton.Item.InteractDistance + GetColliderLength()))
|
||||||
{
|
{
|
||||||
closestButton.Item.TryInteract(character, false, true);
|
if (pressButton)
|
||||||
buttonPressCooldown = ButtonPressInterval;
|
{
|
||||||
|
if (closestButton.Item.TryInteract(character, forceSelectKey: true))
|
||||||
|
{
|
||||||
|
lastDoor = (door, shouldBeOpen);
|
||||||
|
buttonPressCooldown = 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buttonPressCooldown = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -627,6 +689,7 @@ namespace Barotrauma
|
|||||||
// The button is on the wrong side of the door or a wall
|
// The button is on the wrong side of the door or a wall
|
||||||
currentPath.Unreachable = true;
|
currentPath.Unreachable = true;
|
||||||
}
|
}
|
||||||
|
lastDoor = (null, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -207,7 +207,8 @@ namespace Barotrauma
|
|||||||
var cells = Level.Loaded.GetCells(character.WorldPosition, 1);
|
var cells = Level.Loaded.GetCells(character.WorldPosition, 1);
|
||||||
if (cells.Count > 0)
|
if (cells.Count > 0)
|
||||||
{
|
{
|
||||||
float closestDist = float.PositiveInfinity;
|
//ignore walls more than 200 meters away
|
||||||
|
float closestDist = 200.0f * 200.0f;
|
||||||
foreach (Voronoi2.VoronoiCell cell in cells)
|
foreach (Voronoi2.VoronoiCell cell in cells)
|
||||||
{
|
{
|
||||||
foreach (Voronoi2.GraphEdge edge in cell.Edges)
|
foreach (Voronoi2.GraphEdge edge in cell.Edges)
|
||||||
|
|||||||
@@ -283,9 +283,9 @@ namespace Barotrauma
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public float CalculatePriority()
|
public float CalculatePriority()
|
||||||
{
|
{
|
||||||
|
ForceWalk = false;
|
||||||
Priority = GetPriority();
|
Priority = GetPriority();
|
||||||
ForceHighestPriority = false;
|
ForceHighestPriority = false;
|
||||||
ForceWalk = false;
|
|
||||||
return Priority;
|
return Priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,5 +501,34 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static bool CanEquip(Character character, Item item)
|
||||||
|
{
|
||||||
|
bool canEquip = item != null;
|
||||||
|
if (canEquip && !item.AllowedSlots.Contains(InvSlotType.Any))
|
||||||
|
{
|
||||||
|
canEquip = false;
|
||||||
|
var inv = character.Inventory;
|
||||||
|
foreach (var allowedSlot in item.AllowedSlots)
|
||||||
|
{
|
||||||
|
foreach (var slotType in inv.SlotTypes)
|
||||||
|
{
|
||||||
|
if (!allowedSlot.HasFlag(slotType)) { continue; }
|
||||||
|
for (int i = 0; i < inv.Capacity; i++)
|
||||||
|
{
|
||||||
|
canEquip = true;
|
||||||
|
if (allowedSlot.HasFlag(inv.SlotTypes[i]) && inv.GetItemAt(i) != null)
|
||||||
|
{
|
||||||
|
canEquip = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return canEquip;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool CanEquip(Item item) => CanEquip(character, item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,15 +68,12 @@ namespace Barotrauma
|
|||||||
protected override void OnObjectiveCompleted(AIObjective objective, Item target)
|
protected override void OnObjectiveCompleted(AIObjective objective, Item target)
|
||||||
=> HumanAIController.RemoveTargets<AIObjectiveCleanupItems, Item>(character, target);
|
=> HumanAIController.RemoveTargets<AIObjectiveCleanupItems, Item>(character, target);
|
||||||
|
|
||||||
private static bool IsItemInsideValidSubmarine(Item item, Character character)
|
public static bool IsItemInsideValidSubmarine(Item item, Character character)
|
||||||
{
|
{
|
||||||
if (item.CurrentHull == null) { return false; }
|
if (item.CurrentHull == null) { return false; }
|
||||||
if (item.Submarine == null) { return false; }
|
if (item.Submarine == null) { return false; }
|
||||||
if (item.Submarine.TeamID != character.TeamID) { return false; }
|
if (item.Submarine.TeamID != character.TeamID) { return false; }
|
||||||
if (character.Submarine != null)
|
if (character.Submarine != null && !character.Submarine.IsConnectedTo(item.Submarine)) { return false; }
|
||||||
{
|
|
||||||
if (!character.Submarine.IsConnectedTo(item.Submarine)) { return false; }
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,29 +126,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool canEquip = true;
|
return CanEquip(character, item);
|
||||||
if (!item.AllowedSlots.Contains(InvSlotType.Any))
|
|
||||||
{
|
|
||||||
canEquip = false;
|
|
||||||
var inv = character.Inventory;
|
|
||||||
foreach (var allowedSlot in item.AllowedSlots)
|
|
||||||
{
|
|
||||||
foreach (var slotType in inv.SlotTypes)
|
|
||||||
{
|
|
||||||
if (!allowedSlot.HasFlag(slotType)) { continue; }
|
|
||||||
for (int i = 0; i < inv.Capacity; i++)
|
|
||||||
{
|
|
||||||
canEquip = true;
|
|
||||||
if (allowedSlot.HasFlag(inv.SlotTypes[i]) && inv.GetItemAt(i) != null)
|
|
||||||
{
|
|
||||||
canEquip = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return canEquip;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnDeselected()
|
public override void OnDeselected()
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ namespace Barotrauma
|
|||||||
public CombatMode Mode { get; private set; }
|
public CombatMode Mode { get; private set; }
|
||||||
|
|
||||||
private bool IsOffensiveOrArrest => initialMode == CombatMode.Offensive || initialMode == CombatMode.Arrest;
|
private bool IsOffensiveOrArrest => initialMode == CombatMode.Offensive || initialMode == CombatMode.Arrest;
|
||||||
private bool TargetEliminated => IsEnemyDisabled || (Enemy.IsUnconscious && Enemy.Params.Health.ConstantHealthRegeneration <= 0.0f);
|
private bool TargetEliminated => IsEnemyDisabled || Enemy.IsUnconscious && Enemy.Params.Health.ConstantHealthRegeneration <= 0.0f || Enemy.IsHuman && Enemy.HasEquippedItem("handlocker") && !character.IsInstigator;
|
||||||
private bool IsEnemyDisabled => Enemy == null || Enemy.Removed || Enemy.IsDead;
|
private bool IsEnemyDisabled => Enemy == null || Enemy.Removed || Enemy.IsDead;
|
||||||
|
|
||||||
private float AimSpeed => HumanAIController.AimSpeed;
|
private float AimSpeed => HumanAIController.AimSpeed;
|
||||||
@@ -158,7 +158,7 @@ namespace Barotrauma
|
|||||||
return Priority;
|
return Priority;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
float damageFactor = MathUtils.InverseLerp(0.0f, 5.0f, HumanAIController.GetDamageDoneByAttacker(Enemy) / 100.0f);
|
float damageFactor = MathUtils.InverseLerp(0.0f, 5.0f, character.GetDamageDoneByAttacker(Enemy) / 100.0f);
|
||||||
Priority = TargetEliminated ? 0 : Math.Min((95 + damageFactor) * PriorityModifier, 100);
|
Priority = TargetEliminated ? 0 : Math.Min((95 + damageFactor) * PriorityModifier, 100);
|
||||||
return Priority;
|
return Priority;
|
||||||
}
|
}
|
||||||
@@ -177,11 +177,12 @@ namespace Barotrauma
|
|||||||
ignoredWeapons.Clear();
|
ignoredWeapons.Clear();
|
||||||
ignoreWeaponTimer = ignoredWeaponsClearTime;
|
ignoreWeaponTimer = ignoredWeaponsClearTime;
|
||||||
}
|
}
|
||||||
if (findSafety != null)
|
bool isCurrentObjective = objectiveManager.IsCurrentObjective<AIObjectiveFightIntruders>();
|
||||||
|
if (findSafety != null && isCurrentObjective)
|
||||||
{
|
{
|
||||||
findSafety.Priority = 0;
|
findSafety.Priority = 0;
|
||||||
}
|
}
|
||||||
if (!AllowCoolDown && !character.IsOnPlayerTeam && !objectiveManager.IsCurrentObjective<AIObjectiveFightIntruders>())
|
if (!AllowCoolDown && !character.IsOnPlayerTeam && !isCurrentObjective)
|
||||||
{
|
{
|
||||||
distanceTimer -= deltaTime;
|
distanceTimer -= deltaTime;
|
||||||
if (distanceTimer < 0)
|
if (distanceTimer < 0)
|
||||||
@@ -204,13 +205,18 @@ namespace Barotrauma
|
|||||||
|
|
||||||
protected override void Act(float deltaTime)
|
protected override void Act(float deltaTime)
|
||||||
{
|
{
|
||||||
|
if (IsEnemyDisabled)
|
||||||
|
{
|
||||||
|
IsCompleted = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (AllowCoolDown)
|
if (AllowCoolDown)
|
||||||
{
|
{
|
||||||
coolDownTimer -= deltaTime;
|
coolDownTimer -= deltaTime;
|
||||||
}
|
}
|
||||||
if (seekAmmunitionObjective == null && seekWeaponObjective == null)
|
if (seekAmmunitionObjective == null && seekWeaponObjective == null)
|
||||||
{
|
{
|
||||||
if (Mode != CombatMode.Retreat && TryArm() && !IsEnemyDisabled)
|
if (Mode != CombatMode.Retreat && TryArm())
|
||||||
{
|
{
|
||||||
OperateWeapon(deltaTime);
|
OperateWeapon(deltaTime);
|
||||||
}
|
}
|
||||||
@@ -283,10 +289,12 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
AskHelp();
|
||||||
Retreat(deltaTime);
|
Retreat(deltaTime);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CombatMode.Retreat:
|
case CombatMode.Retreat:
|
||||||
|
AskHelp();
|
||||||
Retreat(deltaTime);
|
Retreat(deltaTime);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -363,6 +371,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (WeaponComponent == null)
|
if (WeaponComponent == null)
|
||||||
{
|
{
|
||||||
|
SpeakNoWeapons();
|
||||||
Mode = CombatMode.Retreat;
|
Mode = CombatMode.Retreat;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -409,6 +418,7 @@ namespace Barotrauma
|
|||||||
onCompleted: () => RemoveSubObjective(ref seekWeaponObjective),
|
onCompleted: () => RemoveSubObjective(ref seekWeaponObjective),
|
||||||
onAbandon: () =>
|
onAbandon: () =>
|
||||||
{
|
{
|
||||||
|
SpeakNoWeapons();
|
||||||
RemoveSubObjective(ref seekWeaponObjective);
|
RemoveSubObjective(ref seekWeaponObjective);
|
||||||
Mode = CombatMode.Retreat;
|
Mode = CombatMode.Retreat;
|
||||||
});
|
});
|
||||||
@@ -680,6 +690,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
SpeakNoWeapons();
|
||||||
Weapon = null;
|
Weapon = null;
|
||||||
Mode = CombatMode.Retreat;
|
Mode = CombatMode.Retreat;
|
||||||
return false;
|
return false;
|
||||||
@@ -892,7 +903,7 @@ namespace Barotrauma
|
|||||||
TryAddSubObjective(ref seekAmmunitionObjective,
|
TryAddSubObjective(ref seekAmmunitionObjective,
|
||||||
constructor: () => new AIObjectiveContainItem(character, ammunitionIdentifiers, Weapon.GetComponent<ItemContainer>(), objectiveManager)
|
constructor: () => new AIObjectiveContainItem(character, ammunitionIdentifiers, Weapon.GetComponent<ItemContainer>(), objectiveManager)
|
||||||
{
|
{
|
||||||
targetItemCount = Weapon.GetComponent<ItemContainer>().Capacity,
|
ItemCount = Weapon.GetComponent<ItemContainer>().Capacity,
|
||||||
checkInventory = false
|
checkInventory = false
|
||||||
},
|
},
|
||||||
onCompleted: () => RemoveSubObjective(ref seekAmmunitionObjective),
|
onCompleted: () => RemoveSubObjective(ref seekAmmunitionObjective),
|
||||||
@@ -1099,7 +1110,7 @@ namespace Barotrauma
|
|||||||
if (WeaponComponent is RangedWeapon rangedWeapon)
|
if (WeaponComponent is RangedWeapon rangedWeapon)
|
||||||
{
|
{
|
||||||
// If the weapon is just equipped, we can't shoot just yet.
|
// If the weapon is just equipped, we can't shoot just yet.
|
||||||
if (rangedWeapon.ReloadTimer <= 0)
|
if (rangedWeapon.ReloadTimer <= 0 && !rangedWeapon.HoldTrigger)
|
||||||
{
|
{
|
||||||
reloadTime = rangedWeapon.Reload;
|
reloadTime = rangedWeapon.Reload;
|
||||||
}
|
}
|
||||||
@@ -1155,6 +1166,21 @@ namespace Barotrauma
|
|||||||
retreatTarget = null;
|
retreatTarget = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SpeakNoWeapons() => Speak("dialogcombatnoweapons", delay: 0, minDuration: 30);
|
||||||
|
private void AskHelp() => Speak("dialogcombatretreating", delay: Rand.Range(0, 1), minDuration: 20);
|
||||||
|
|
||||||
|
private void Speak(string textIdentifier, float delay, float minDuration)
|
||||||
|
{
|
||||||
|
if (character.IsOnPlayerTeam && !character.IsInFriendlySub)
|
||||||
|
{
|
||||||
|
string msg = TextManager.Get(textIdentifier, true);
|
||||||
|
if (msg != null)
|
||||||
|
{
|
||||||
|
character.Speak(msg, identifier: textIdentifier, delay: delay, minDurationBetweenSimilar: minDuration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//private float CalculateEnemyStrength()
|
//private float CalculateEnemyStrength()
|
||||||
//{
|
//{
|
||||||
// float enemyStrength = 0;
|
// float enemyStrength = 0;
|
||||||
|
|||||||
@@ -11,12 +11,11 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public Func<Item, float> GetItemPriority;
|
public Func<Item, float> GetItemPriority;
|
||||||
|
|
||||||
public int targetItemCount = 1;
|
|
||||||
public string[] ignoredContainerIdentifiers;
|
public string[] ignoredContainerIdentifiers;
|
||||||
public bool checkInventory = true;
|
public bool checkInventory = true;
|
||||||
|
|
||||||
//if the item can't be found, spawn it in the character's inventory (used by outpost NPCs)
|
//if the item can't be found, spawn it in the character's inventory (used by outpost NPCs and in some cases also enemy NPCs, like pirates)
|
||||||
private bool spawnItemIfNotFound = false;
|
private readonly bool spawnItemIfNotFound;
|
||||||
|
|
||||||
//can either be a tag or an identifier
|
//can either be a tag or an identifier
|
||||||
public readonly string[] itemIdentifiers;
|
public readonly string[] itemIdentifiers;
|
||||||
@@ -35,9 +34,24 @@ namespace Barotrauma
|
|||||||
public bool Equip { get; set; }
|
public bool Equip { get; set; }
|
||||||
public bool RemoveEmpty { get; set; } = true;
|
public bool RemoveEmpty { get; set; } = true;
|
||||||
public bool RemoveExisting { get; set; }
|
public bool RemoveExisting { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Only remove existing items when the contain target can't be put in the inventory
|
||||||
|
/// </summary>
|
||||||
|
public bool RemoveExistingWhenNecessary { get; set; }
|
||||||
|
public Func<Item, bool> RemoveExistingPredicate { get; set; }
|
||||||
|
public int? RemoveMax { get; set; }
|
||||||
|
|
||||||
public bool MoveWholeStack { get; set; }
|
public bool MoveWholeStack { get; set; }
|
||||||
|
|
||||||
|
private int _itemCount = 1;
|
||||||
|
public int ItemCount
|
||||||
|
{
|
||||||
|
get { return _itemCount; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_itemCount = Math.Max(value, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public AIObjectiveContainItem(Character character, Item item, ItemContainer container, AIObjectiveManager objectiveManager, float priorityModifier = 1)
|
public AIObjectiveContainItem(Character character, Item item, ItemContainer container, AIObjectiveManager objectiveManager, float priorityModifier = 1)
|
||||||
: base(character, objectiveManager, priorityModifier)
|
: base(character, objectiveManager, priorityModifier)
|
||||||
@@ -83,7 +97,7 @@ namespace Barotrauma
|
|||||||
containedItemCount++;
|
containedItemCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return containedItemCount >= targetItemCount;
|
return containedItemCount >= ItemCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,9 +120,9 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
if (character.CanInteractWith(container.Item, checkLinked: false))
|
if (character.CanInteractWith(container.Item, checkLinked: false))
|
||||||
{
|
{
|
||||||
if (RemoveExisting)
|
if (RemoveExisting || (RemoveExistingWhenNecessary && !container.Inventory.CanBePut(item)))
|
||||||
{
|
{
|
||||||
HumanAIController.UnequipContainedItems(container.Item);
|
HumanAIController.UnequipContainedItems(container.Item, predicate: RemoveExistingPredicate, unequipMax: RemoveMax);
|
||||||
}
|
}
|
||||||
else if (RemoveEmpty)
|
else if (RemoveEmpty)
|
||||||
{
|
{
|
||||||
@@ -127,7 +141,6 @@ namespace Barotrauma
|
|||||||
container.Inventory.TryPutItem(item, null);
|
container.Inventory.TryPutItem(item, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IsCompleted = true;
|
IsCompleted = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,11 @@ namespace Barotrauma
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool DropIfFails { get; set; } = true;
|
public bool DropIfFails { get; set; } = true;
|
||||||
|
|
||||||
|
public bool RemoveExistingWhenNecessary { get; set; }
|
||||||
|
public Func<Item, bool> RemoveExistingPredicate { get; set; }
|
||||||
|
public int? RemoveExistingMax { get; set; }
|
||||||
|
public string AbandonGetItemDialogueIdentifier { get; set; }
|
||||||
|
|
||||||
public AIObjectiveDecontainItem(Character character, Item targetItem, AIObjectiveManager objectiveManager, ItemContainer sourceContainer = null, ItemContainer targetContainer = null, float priorityModifier = 1)
|
public AIObjectiveDecontainItem(Character character, Item targetItem, AIObjectiveManager objectiveManager, ItemContainer sourceContainer = null, ItemContainer targetContainer = null, float priorityModifier = 1)
|
||||||
: base(character, objectiveManager, priorityModifier)
|
: base(character, objectiveManager, priorityModifier)
|
||||||
{
|
{
|
||||||
@@ -86,6 +91,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
if (itemToDecontain.Container != sourceContainer.Item)
|
if (itemToDecontain.Container != sourceContainer.Item)
|
||||||
{
|
{
|
||||||
|
itemToDecontain.Drop(character);
|
||||||
IsCompleted = true;
|
IsCompleted = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -98,7 +104,12 @@ namespace Barotrauma
|
|||||||
if (getItemObjective == null && !itemToDecontain.IsOwnedBy(character))
|
if (getItemObjective == null && !itemToDecontain.IsOwnedBy(character))
|
||||||
{
|
{
|
||||||
TryAddSubObjective(ref getItemObjective,
|
TryAddSubObjective(ref getItemObjective,
|
||||||
constructor: () => new AIObjectiveGetItem(character, targetItem, objectiveManager, Equip) { TakeWholeStack = this.TakeWholeStack },
|
constructor: () => new AIObjectiveGetItem(character, targetItem, objectiveManager, Equip)
|
||||||
|
{
|
||||||
|
CannotFindDialogueIdentifierOverride = AbandonGetItemDialogueIdentifier,
|
||||||
|
SpeakIfFails = AbandonGetItemDialogueIdentifier != null,
|
||||||
|
TakeWholeStack = this.TakeWholeStack
|
||||||
|
},
|
||||||
onAbandon: () => Abandon = true);
|
onAbandon: () => Abandon = true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -110,6 +121,9 @@ namespace Barotrauma
|
|||||||
MoveWholeStack = TakeWholeStack,
|
MoveWholeStack = TakeWholeStack,
|
||||||
Equip = Equip,
|
Equip = Equip,
|
||||||
RemoveEmpty = false,
|
RemoveEmpty = false,
|
||||||
|
RemoveExistingWhenNecessary = RemoveExistingWhenNecessary,
|
||||||
|
RemoveExistingPredicate = RemoveExistingPredicate,
|
||||||
|
RemoveMax = RemoveExistingMax,
|
||||||
GetItemPriority = GetItemPriority,
|
GetItemPriority = GetItemPriority,
|
||||||
ignoredContainerIdentifiers = sourceContainer != null ? new string[] { sourceContainer.Item.Prefab.Identifier } : null
|
ignoredContainerIdentifiers = sourceContainer != null ? new string[] { sourceContainer.Item.Prefab.Identifier } : null
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
protected override AIObjective ObjectiveConstructor(Character target)
|
protected override AIObjective ObjectiveConstructor(Character target)
|
||||||
{
|
{
|
||||||
AIObjectiveCombat.CombatMode combatMode = target.IsEscorted && character.TeamID == CharacterTeamType.Team1 ? AIObjectiveCombat.CombatMode.Arrest : AIObjectiveCombat.CombatMode.Offensive;
|
AIObjectiveCombat.CombatMode combatMode = ShouldArrest(target, character) ? AIObjectiveCombat.CombatMode.Arrest : AIObjectiveCombat.CombatMode.Offensive;
|
||||||
var combatObjective = new AIObjectiveCombat(character, target, combatMode, objectiveManager, PriorityModifier);
|
var combatObjective = new AIObjectiveCombat(character, target, combatMode, objectiveManager, PriorityModifier);
|
||||||
if (character.TeamID == CharacterTeamType.FriendlyNPC && target.TeamID == CharacterTeamType.Team1 && GameMain.GameSession?.GameMode is CampaignMode campaign)
|
if (character.TeamID == CharacterTeamType.FriendlyNPC && target.TeamID == CharacterTeamType.Team1 && GameMain.GameSession?.GameMode is CampaignMode campaign)
|
||||||
{
|
{
|
||||||
@@ -41,7 +41,7 @@ namespace Barotrauma
|
|||||||
combatObjective.holdFireCondition = () =>
|
combatObjective.holdFireCondition = () =>
|
||||||
{
|
{
|
||||||
//hold fire while the enemy is in the airlock (except if they've attacked us)
|
//hold fire while the enemy is in the airlock (except if they've attacked us)
|
||||||
if (HumanAIController.GetDamageDoneByAttacker(target) > 0.0f) { return false; }
|
if (character.GetDamageDoneByAttacker(target) > 0.0f) { return false; }
|
||||||
return target.CurrentHull == null || target.CurrentHull.OutpostModuleTags.Any(t => t.Equals("airlock", System.StringComparison.OrdinalIgnoreCase));
|
return target.CurrentHull == null || target.CurrentHull.OutpostModuleTags.Any(t => t.Equals("airlock", System.StringComparison.OrdinalIgnoreCase));
|
||||||
};
|
};
|
||||||
character.Speak(TextManager.Get("dialogenteroutpostwarning"), null, Rand.Range(0.5f, 1.0f), "leaveoutpostwarning", 30.0f);
|
character.Speak(TextManager.Get("dialogenteroutpostwarning"), null, Rand.Range(0.5f, 1.0f), "leaveoutpostwarning", 30.0f);
|
||||||
@@ -65,7 +65,13 @@ namespace Barotrauma
|
|||||||
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; }
|
if (target.HasAbilityFlag(AbilityFlags.IgnoredByEnemyAI)) { return false; }
|
||||||
|
if (ShouldArrest(target, character) && target.HasEquippedItem("handlocker")) { return false; }
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool ShouldArrest(Character target, Character character)
|
||||||
|
{
|
||||||
|
return target != null && target.IsEscorted && character.TeamID == CharacterTeamType.Team1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,9 +52,11 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Priority = (objectiveManager.IsCurrentOrder<AIObjectiveGoTo>() ||
|
Priority = (
|
||||||
objectiveManager.IsCurrentOrder<AIObjectiveReturn>() ||
|
objectiveManager.HasOrder<AIObjectiveGoTo>(o => o.Priority > 0) ||
|
||||||
objectiveManager.Objectives.Any(o => o.Priority > 0 && o is AIObjectiveCombat))
|
objectiveManager.HasOrder<AIObjectiveReturn>(o => o.Priority > 0) ||
|
||||||
|
objectiveManager.HasActiveObjective<AIObjectiveRescue>() ||
|
||||||
|
objectiveManager.Objectives.Any(o => o is AIObjectiveCombat && o.Priority > 0))
|
||||||
&& HumanAIController.HasDivingSuit(character) ? 0 : 100;
|
&& HumanAIController.HasDivingSuit(character) ? 0 : 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace Barotrauma
|
|||||||
public float TargetCondition { get; set; } = 1;
|
public float TargetCondition { get; set; } = 1;
|
||||||
public bool AllowDangerousPressure { get; set; }
|
public bool AllowDangerousPressure { get; set; }
|
||||||
|
|
||||||
private readonly ImmutableArray<string> identifiersOrTags;
|
public readonly ImmutableArray<string> IdentifiersOrTags;
|
||||||
|
|
||||||
//if the item can't be found, spawn it in the character's inventory (used by outpost NPCs)
|
//if the item can't be found, spawn it in the character's inventory (used by outpost NPCs)
|
||||||
private bool spawnItemIfNotFound = false;
|
private bool spawnItemIfNotFound = false;
|
||||||
@@ -58,6 +58,17 @@ namespace Barotrauma
|
|||||||
public bool EvaluateCombatPriority { get; set; }
|
public bool EvaluateCombatPriority { get; set; }
|
||||||
public bool CheckPathForEachItem { get; set; }
|
public bool CheckPathForEachItem { get; set; }
|
||||||
public bool SpeakIfFails { get; set; }
|
public bool SpeakIfFails { get; set; }
|
||||||
|
public string CannotFindDialogueIdentifierOverride { get; set; }
|
||||||
|
|
||||||
|
private int _itemCount = 1;
|
||||||
|
public int ItemCount
|
||||||
|
{
|
||||||
|
get { return _itemCount; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_itemCount = Math.Max(value, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public InvSlotType? EquipSlotType { get; set; }
|
public InvSlotType? EquipSlotType { get; set; }
|
||||||
|
|
||||||
@@ -81,7 +92,7 @@ namespace Barotrauma
|
|||||||
Equip = equip;
|
Equip = equip;
|
||||||
this.spawnItemIfNotFound = spawnItemIfNotFound;
|
this.spawnItemIfNotFound = spawnItemIfNotFound;
|
||||||
this.checkInventory = checkInventory;
|
this.checkInventory = checkInventory;
|
||||||
this.identifiersOrTags = ParseGearTags(identifiersOrTags).ToImmutableArray();
|
IdentifiersOrTags = ParseGearTags(identifiersOrTags).ToImmutableArray();
|
||||||
ignoredIdentifiersOrTags = ParseIgnoredTags(identifiersOrTags).ToArray();
|
ignoredIdentifiersOrTags = ParseIgnoredTags(identifiersOrTags).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,7 +124,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private bool CheckInventory()
|
private bool CheckInventory()
|
||||||
{
|
{
|
||||||
if (identifiersOrTags == null) { return false; }
|
if (IdentifiersOrTags == null) { return false; }
|
||||||
var item = character.Inventory.FindItem(i => CheckItem(i), recursive: true);
|
var item = character.Inventory.FindItem(i => CheckItem(i), recursive: true);
|
||||||
if (item != null)
|
if (item != null)
|
||||||
{
|
{
|
||||||
@@ -123,6 +134,19 @@ namespace Barotrauma
|
|||||||
return item != null;
|
return item != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool CountItems()
|
||||||
|
{
|
||||||
|
int itemCount = 0;
|
||||||
|
foreach (Item it in character.Inventory.AllItems)
|
||||||
|
{
|
||||||
|
if (CheckItem(it))
|
||||||
|
{
|
||||||
|
itemCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return itemCount >= ItemCount;
|
||||||
|
}
|
||||||
|
|
||||||
protected override void Act(float deltaTime)
|
protected override void Act(float deltaTime)
|
||||||
{
|
{
|
||||||
if (character.LockHands)
|
if (character.LockHands)
|
||||||
@@ -135,7 +159,7 @@ namespace Barotrauma
|
|||||||
Abandon = true;
|
Abandon = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (identifiersOrTags != null && !isDoneSeeking)
|
if (IdentifiersOrTags != null && !isDoneSeeking)
|
||||||
{
|
{
|
||||||
if (checkInventory)
|
if (checkInventory)
|
||||||
{
|
{
|
||||||
@@ -152,7 +176,7 @@ namespace Barotrauma
|
|||||||
if (dangerousPressure)
|
if (dangerousPressure)
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
string itemName = targetItem != null ? targetItem.Name : identifiersOrTags.FirstOrDefault();
|
string itemName = targetItem != null ? targetItem.Name : IdentifiersOrTags.FirstOrDefault();
|
||||||
DebugConsole.NewMessage($"{character.Name}: Seeking item ({itemName}) aborted, because the pressure is dangerous.", Color.Yellow);
|
DebugConsole.NewMessage($"{character.Name}: Seeking item ({itemName}) aborted, because the pressure is dangerous.", Color.Yellow);
|
||||||
#endif
|
#endif
|
||||||
Abandon = true;
|
Abandon = true;
|
||||||
@@ -245,7 +269,18 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IsCompleted = true;
|
if (IdentifiersOrTags == null)
|
||||||
|
{
|
||||||
|
IsCompleted = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IsCompleted = CountItems();
|
||||||
|
if (!IsCompleted)
|
||||||
|
{
|
||||||
|
ResetInternal();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -297,7 +332,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private void FindTargetItem()
|
private void FindTargetItem()
|
||||||
{
|
{
|
||||||
if (identifiersOrTags == null)
|
if (IdentifiersOrTags == null)
|
||||||
{
|
{
|
||||||
if (targetItem == null)
|
if (targetItem == null)
|
||||||
{
|
{
|
||||||
@@ -316,7 +351,7 @@ namespace Barotrauma
|
|||||||
// Otherwise it will take some time for us to find a valid item when there are multiple items that we can't reach and some that we can.
|
// Otherwise it will take some time for us to find a valid item when there are multiple items that we can't reach and some that we can.
|
||||||
// This is relatively expensive, so let's do this only when it significantly improves the behavior.
|
// This is relatively expensive, so let's do this only when it significantly improves the behavior.
|
||||||
// Only allow one path find call per frame.
|
// Only allow one path find call per frame.
|
||||||
CheckPathForEachItem = priority >= AIObjectiveManager.LowestOrderPriority && (objectiveManager.IsCurrentOrder<AIObjectiveFixLeaks>() || objectiveManager.CurrentOrder is AIObjectiveGoTo gotoOrder && gotoOrder.isFollowOrderObjective);
|
CheckPathForEachItem = priority >= AIObjectiveManager.LowestOrderPriority && (objectiveManager.IsCurrentOrder<AIObjectiveFixLeaks>() || objectiveManager.CurrentOrder is AIObjectiveGoTo gotoOrder && gotoOrder.IsFollowOrderObjective);
|
||||||
}
|
}
|
||||||
bool checkPath = CheckPathForEachItem;
|
bool checkPath = CheckPathForEachItem;
|
||||||
bool hasCalledPathFinder = false;
|
bool hasCalledPathFinder = false;
|
||||||
@@ -430,10 +465,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (spawnItemIfNotFound)
|
if (spawnItemIfNotFound)
|
||||||
{
|
{
|
||||||
if (!(MapEntityPrefab.List.FirstOrDefault(me => me is ItemPrefab ip && identifiersOrTags.Any(id => id == ip.Identifier || ip.Tags.Contains(id))) is ItemPrefab prefab))
|
if (!(MapEntityPrefab.List.FirstOrDefault(me => me is ItemPrefab ip && IdentifiersOrTags.Any(id => id == ip.Identifier || ip.Tags.Contains(id))) is ItemPrefab prefab))
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
DebugConsole.NewMessage($"{character.Name}: Cannot find an item with the following identifier(s) or tag(s): {string.Join(", ", identifiersOrTags)}, tried to spawn the item but no matching item prefabs were found.", Color.Yellow);
|
DebugConsole.NewMessage($"{character.Name}: Cannot find an item with the following identifier(s) or tag(s): {string.Join(", ", IdentifiersOrTags)}, tried to spawn the item but no matching item prefabs were found.", Color.Yellow);
|
||||||
#endif
|
#endif
|
||||||
Abandon = true;
|
Abandon = true;
|
||||||
}
|
}
|
||||||
@@ -452,7 +487,7 @@ namespace Barotrauma
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
DebugConsole.NewMessage($"{character.Name}: Cannot find an item with the following identifier(s) or tag(s): {string.Join(", ", identifiersOrTags)}", Color.Yellow);
|
DebugConsole.NewMessage($"{character.Name}: Cannot find an item with the following identifier(s) or tag(s): {string.Join(", ", IdentifiersOrTags)}", Color.Yellow);
|
||||||
#endif
|
#endif
|
||||||
Abandon = true;
|
Abandon = true;
|
||||||
}
|
}
|
||||||
@@ -468,13 +503,20 @@ namespace Barotrauma
|
|||||||
// Not yet ready
|
// Not yet ready
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (Equip && EquipSlotType.HasValue)
|
if (IdentifiersOrTags != null && ItemCount > 1)
|
||||||
{
|
{
|
||||||
return character.HasEquippedItem(targetItem, EquipSlotType.Value);
|
return CountItems();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return character.HasItem(targetItem, Equip);
|
if (Equip && EquipSlotType.HasValue)
|
||||||
|
{
|
||||||
|
return character.HasEquippedItem(targetItem, EquipSlotType.Value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return character.HasItem(targetItem, Equip);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -487,7 +529,7 @@ namespace Barotrauma
|
|||||||
if (item.Condition < TargetCondition) { return false; }
|
if (item.Condition < TargetCondition) { return false; }
|
||||||
if (ItemFilter != null && !ItemFilter(item)) { return false; }
|
if (ItemFilter != null && !ItemFilter(item)) { return false; }
|
||||||
if (RequireLoaded && item.Components.Any(i => !i.IsLoaded(character))) { return false; }
|
if (RequireLoaded && item.Components.Any(i => !i.IsLoaded(character))) { return false; }
|
||||||
return identifiersOrTags.Any(id => id == item.Prefab.Identifier || item.HasTag(id) || (AllowVariants && item.Prefab.VariantOf?.Identifier == id));
|
return IdentifiersOrTags.Any(id => id == item.Prefab.Identifier || item.HasTag(id) || (AllowVariants && item.Prefab.VariantOf?.Identifier == id));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Reset()
|
public override void Reset()
|
||||||
@@ -528,7 +570,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (character.IsOnPlayerTeam && objectiveManager.CurrentOrder == objectiveManager.CurrentObjective)
|
if (character.IsOnPlayerTeam && objectiveManager.CurrentOrder == objectiveManager.CurrentObjective)
|
||||||
{
|
{
|
||||||
string msg = TextManager.Get("dialogcannotfinditem", true);
|
string msg = TextManager.Get(CannotFindDialogueIdentifierOverride, returnNull: true) ?? TextManager.Get("dialogcannotfinditem", returnNull: true);
|
||||||
if (msg != null)
|
if (msg != null)
|
||||||
{
|
{
|
||||||
character.Speak(msg, identifier: "dialogcannotfinditem", minDurationBetweenSimilar: 20.0f);
|
character.Speak(msg, identifier: "dialogcannotfinditem", minDurationBetweenSimilar: 20.0f);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ namespace Barotrauma
|
|||||||
public override string Identifier { get; set; } = "get items";
|
public override string Identifier { get; set; } = "get items";
|
||||||
public override string DebugTag => $"{Identifier}";
|
public override string DebugTag => $"{Identifier}";
|
||||||
public override bool KeepDivingGearOn => true;
|
public override bool KeepDivingGearOn => true;
|
||||||
|
public override bool AllowMultipleInstances => true;
|
||||||
|
|
||||||
public bool AllowStealing { get; set; }
|
public bool AllowStealing { get; set; }
|
||||||
public bool TakeWholeStack { get; set; }
|
public bool TakeWholeStack { get; set; }
|
||||||
@@ -21,6 +22,7 @@ namespace Barotrauma
|
|||||||
public bool EvaluateCombatPriority { get; set; }
|
public bool EvaluateCombatPriority { get; set; }
|
||||||
public bool CheckPathForEachItem { get; set; }
|
public bool CheckPathForEachItem { get; set; }
|
||||||
public bool RequireLoaded { get; set; }
|
public bool RequireLoaded { get; set; }
|
||||||
|
public bool RequireAllItems { get; set; }
|
||||||
|
|
||||||
private readonly ImmutableArray<string> gearTags;
|
private readonly ImmutableArray<string> gearTags;
|
||||||
private readonly string[] ignoredTags;
|
private readonly string[] ignoredTags;
|
||||||
@@ -47,9 +49,11 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
foreach (string tag in gearTags)
|
foreach (string tag in gearTags)
|
||||||
{
|
{
|
||||||
|
if (subObjectives.Any(so => so is AIObjectiveGetItem getItem && getItem.IdentifiersOrTags.Contains(tag))) { continue; }
|
||||||
|
int count = gearTags.Count(t => t == tag);
|
||||||
AIObjectiveGetItem? getItem = null;
|
AIObjectiveGetItem? getItem = null;
|
||||||
TryAddSubObjective(ref getItem, () =>
|
TryAddSubObjective(ref getItem, () =>
|
||||||
new AIObjectiveGetItem(character, tag, objectiveManager, Equip, CheckInventory)
|
new AIObjectiveGetItem(character, tag, objectiveManager, Equip, CheckInventory && count <= 1)
|
||||||
{
|
{
|
||||||
AllowVariants = AllowVariants,
|
AllowVariants = AllowVariants,
|
||||||
Wear = Wear,
|
Wear = Wear,
|
||||||
@@ -57,7 +61,9 @@ namespace Barotrauma
|
|||||||
AllowStealing = AllowStealing,
|
AllowStealing = AllowStealing,
|
||||||
ignoredIdentifiersOrTags = ignoredTags,
|
ignoredIdentifiersOrTags = ignoredTags,
|
||||||
CheckPathForEachItem = CheckPathForEachItem,
|
CheckPathForEachItem = CheckPathForEachItem,
|
||||||
RequireLoaded = RequireLoaded
|
RequireLoaded = RequireLoaded,
|
||||||
|
ItemCount = count,
|
||||||
|
SpeakIfFails = RequireAllItems
|
||||||
},
|
},
|
||||||
onCompleted: () =>
|
onCompleted: () =>
|
||||||
{
|
{
|
||||||
@@ -75,6 +81,10 @@ namespace Barotrauma
|
|||||||
achievedItems.Remove(item);
|
achievedItems.Remove(item);
|
||||||
}
|
}
|
||||||
RemoveSubObjective(ref getItem);
|
RemoveSubObjective(ref getItem);
|
||||||
|
if (RequireAllItems)
|
||||||
|
{
|
||||||
|
Abandon = true;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
subObjectivesCreated = true;
|
subObjectivesCreated = true;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user