0.15.21.0
This commit is contained in:
@@ -1155,7 +1155,7 @@ namespace Barotrauma
|
||||
|
||||
if (afflictionsDirty())
|
||||
{
|
||||
var currentAfflictions = afflictions.Where(a => a.Value == selectedLimb && a.Key.ShouldShowIcon(Character)).Select(a => a.Key);
|
||||
var currentAfflictions = afflictions.Where(a => ShouldDisplayAfflictionOnLimb(a, selectedLimb)).Select(a => a.Key);
|
||||
CreateAfflictionInfos(currentAfflictions);
|
||||
CreateRecommendedTreatments();
|
||||
}
|
||||
@@ -1170,7 +1170,7 @@ namespace Barotrauma
|
||||
//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 (!ShouldDisplayAfflictionOnLimb(kvp, selectedLimb)) { continue; }
|
||||
if (!displayedAfflictions.Any(d => d.affliction == kvp.Key)) { return true; }
|
||||
}
|
||||
//displaying an affliction we no longer have -> dirty
|
||||
@@ -1187,7 +1187,7 @@ namespace Barotrauma
|
||||
afflictionIconContainer.ClearChildren();
|
||||
displayedAfflictions.Clear();
|
||||
|
||||
Affliction mostSevereAffliction = SortAfflictionsBySeverity(afflictions).FirstOrDefault();
|
||||
Affliction mostSevereAffliction = SortAfflictionsBySeverity(afflictions, excludeBuffs: false).FirstOrDefault();
|
||||
GUIButton buttonToSelect = null;
|
||||
|
||||
foreach (Affliction affliction in afflictions)
|
||||
@@ -1779,25 +1779,10 @@ namespace Barotrauma
|
||||
i = 0;
|
||||
foreach (LimbHealth limbHealth in limbHealths)
|
||||
{
|
||||
bool shouldDisplayAffliction(KeyValuePair<Affliction, LimbHealth> kvp, LimbHealth limbHealth)
|
||||
{
|
||||
if (!kvp.Key.ShouldShowIcon(Character)) { return false; }
|
||||
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;
|
||||
}
|
||||
|
||||
afflictionsDisplayedOnLimb.Clear();
|
||||
foreach (var affliction in afflictions)
|
||||
{
|
||||
if (shouldDisplayAffliction(affliction, limbHealth)) { afflictionsDisplayedOnLimb.Add(affliction.Key); }
|
||||
if (ShouldDisplayAfflictionOnLimb(affliction, limbHealth)) { afflictionsDisplayedOnLimb.Add(affliction.Key); }
|
||||
}
|
||||
|
||||
if (!afflictionsDisplayedOnLimb.Any()) { i++; continue; }
|
||||
@@ -1839,6 +1824,22 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private bool ShouldDisplayAfflictionOnLimb(KeyValuePair<Affliction, LimbHealth> kvp, LimbHealth limbHealth)
|
||||
{
|
||||
if (!kvp.Key.ShouldShowIcon(Character)) { return false; }
|
||||
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 == limbHealths.IndexOf(limbHealth);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void DrawLimbAfflictionIcon(SpriteBatch spriteBatch, Affliction affliction, float iconScale, ref Vector2 iconPos)
|
||||
{
|
||||
if (!affliction.ShouldShowIcon(Character) || affliction.Prefab.Icon == null) { return; }
|
||||
|
||||
@@ -438,7 +438,7 @@ namespace Barotrauma
|
||||
Color.White, Color.Black * 0.5f, 0, SmallFont);
|
||||
|
||||
DrawString(spriteBatch, new Vector2(10, 40),
|
||||
$"Bodies: {GameMain.World.BodyList.Count} ({GameMain.World.BodyList.FindAll(b => b.Awake && b.Enabled).Count} awake, {GameMain.World.BodyList.FindAll(b => b.Awake && b.BodyType == BodyType.Dynamic && b.Enabled).Count} dynamic)",
|
||||
$"Bodies: {GameMain.World.BodyList.Count} ({GameMain.World.BodyList.Count(b => b != null && b.Awake && b.Enabled)} awake, {GameMain.World.BodyList.Count(b => b != null && b.Awake && b.BodyType == BodyType.Dynamic && b.Enabled)} dynamic)",
|
||||
Color.White, Color.Black * 0.5f, 0, SmallFont);
|
||||
|
||||
if (Screen.Selected.Cam != null)
|
||||
|
||||
@@ -476,7 +476,9 @@ namespace Barotrauma
|
||||
DebugConsole.Log("Selected content packages: " + string.Join(", ", Config.AllEnabledPackages.Select(cp => cp.Name)));
|
||||
}
|
||||
|
||||
#if !DEBUG
|
||||
GameAnalyticsManager.InitIfConsented();
|
||||
#endif
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
|
||||
@@ -535,6 +535,9 @@ namespace Barotrauma
|
||||
return false;
|
||||
}
|
||||
};
|
||||
#if DEBUG
|
||||
statisticsTickBox.Enabled = false;
|
||||
#endif
|
||||
void updateGATickBoxToolTip()
|
||||
=> statisticsTickBox.ToolTip = TextManager.Get($"GameAnalyticsStatus.{GameAnalyticsManager.UserConsented}");
|
||||
updateGATickBoxToolTip();
|
||||
|
||||
@@ -38,9 +38,9 @@ namespace Barotrauma.Items.Components
|
||||
private bool qteSuccess;
|
||||
|
||||
private float qteTimer;
|
||||
private const float qteTime = 0.5f;
|
||||
private const float QteDuration = 0.5f;
|
||||
private float qteCooldown;
|
||||
private const float qteCooldownTime = 0.5f;
|
||||
private const float QteCooldownDuration = 0.5f;
|
||||
|
||||
public float FakeBrokenTimer;
|
||||
|
||||
@@ -155,7 +155,7 @@ namespace Barotrauma.Items.Components
|
||||
IgnoreLayoutGroups = true
|
||||
};
|
||||
|
||||
qteTimer = qteTime;
|
||||
qteTimer = QteDuration;
|
||||
|
||||
repairButtonText = TextManager.Get("RepairButton");
|
||||
repairingText = TextManager.Get("Repairing");
|
||||
@@ -276,14 +276,13 @@ namespace Barotrauma.Items.Components
|
||||
qteCooldown -= deltaTime;
|
||||
if (qteCooldown <= 0.0f)
|
||||
{
|
||||
qteTimer = qteTime;
|
||||
qteTimer = QteDuration;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qteTimer -= deltaTime * (qteTimer / qteTime);
|
||||
if (qteTimer < 0.0f) qteTimer = qteTime;
|
||||
|
||||
qteTimer -= deltaTime * (qteTimer / QteDuration);
|
||||
if (qteTimer < 0.0f) { qteTimer = QteDuration; }
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -307,11 +306,11 @@ namespace Barotrauma.Items.Components
|
||||
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);
|
||||
progressBar.Color = ToolBox.GradientLerp(qteCooldown / QteCooldownDuration, progressBar.Color, qteSliderColor, Color.White);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (qteTimer / qteTime <= item.Condition / item.MaxCondition)
|
||||
if (qteTimer / QteDuration <= item.Condition / item.MaxCondition)
|
||||
{
|
||||
qteSliderColor = Color.Lerp(qteSliderColor, GUI.Style.Green, 0.5f);
|
||||
}
|
||||
@@ -319,7 +318,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
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),
|
||||
new Rectangle(sliderRect.X + (int)((qteTimer / QteDuration) * sliderRect.Width), sliderRect.Y - 5, 2, sliderRect.Height + 10),
|
||||
qteSliderColor, true);
|
||||
|
||||
if (item.Condition > defaultMaxCondition)
|
||||
@@ -341,7 +340,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
SabotageButton.Visible = character.IsTraitor;
|
||||
SabotageButton.IgnoreLayoutGroups = !SabotageButton.Visible;
|
||||
SabotageButton.Enabled = (currentFixerAction == FixActions.None || (CurrentFixer == character && currentFixerAction != FixActions.Sabotage)) && character.IsTraitor && IsBelowRepairThreshold;
|
||||
SabotageButton.Enabled = (currentFixerAction == FixActions.None || (CurrentFixer == character && currentFixerAction != FixActions.Sabotage)) && character.IsTraitor && item.ConditionPercentage > MinSabotageCondition;
|
||||
SabotageButton.Text = (currentFixerAction == FixActions.None || CurrentFixer != character || currentFixerAction != FixActions.Sabotage || !character.IsTraitor) ?
|
||||
sabotageButtonText :
|
||||
sabotagingText + new string('.', ((int)(Timing.TotalTime * 2.0f) % 3) + 1);
|
||||
@@ -408,7 +407,8 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (currentFixerAction == FixActions.Repair)
|
||||
{
|
||||
qteSuccess = qteCooldown <= 0.0f && qteTimer / qteTime <= item.Condition / item.MaxCondition;
|
||||
float defaultMaxCondition = item.MaxCondition / item.MaxRepairConditionMultiplier;
|
||||
qteSuccess = qteCooldown <= 0.0f && qteTimer / QteDuration <= item.Condition / defaultMaxCondition;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -420,8 +420,8 @@ namespace Barotrauma.Items.Components
|
||||
SoundPlayer.PlayUISound(qteSuccess ? GUISoundType.IncreaseQuantity : GUISoundType.DecreaseQuantity);
|
||||
|
||||
//on failure during cooldown reset cursor to beginning
|
||||
if (!qteSuccess && qteCooldown > 0.0f) { qteTimer = qteTime; }
|
||||
qteCooldown = qteCooldownTime;
|
||||
if (!qteSuccess && qteCooldown > 0.0f) { qteTimer = QteDuration; }
|
||||
qteCooldown = QteCooldownDuration;
|
||||
//this will be set on button down so we can reset it here
|
||||
requestStartFixAction = FixActions.None;
|
||||
item.CreateClientEvent(this);
|
||||
@@ -438,7 +438,11 @@ namespace Barotrauma.Items.Components
|
||||
currentFixerAction = (FixActions)msg.ReadRangedInteger(0, 2);
|
||||
CurrentFixer = currentFixerID != 0 ? Entity.FindEntityByID(currentFixerID) as Character : null;
|
||||
item.MaxRepairConditionMultiplier = GetMaxRepairConditionMultiplier(CurrentFixer);
|
||||
repairBoost = msg.ReadSingle();
|
||||
if (CurrentFixer == null)
|
||||
{
|
||||
qteTimer = QteDuration;
|
||||
qteCooldown = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
||||
|
||||
@@ -314,7 +314,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
string colorStr = XMLExtensions.ColorToString(!item.AllowStealing ? GUI.Style.Red : Color.White);
|
||||
string colorStr = XMLExtensions.ColorToString(item.SpawnedInCurrentOutpost && !item.AllowStealing ? GUI.Style.Red : Color.White);
|
||||
|
||||
toolTip = $"‖color:{colorStr}‖{name}‖color:end‖";
|
||||
if (item.GetComponent<Quality>() != null)
|
||||
|
||||
@@ -648,12 +648,18 @@ namespace Barotrauma
|
||||
if (linkedTo.Contains(otherEntity))
|
||||
{
|
||||
linkedTo.Remove(otherEntity);
|
||||
if (otherEntity.linkedTo != null && otherEntity.linkedTo.Contains(this)) otherEntity.linkedTo.Remove(this);
|
||||
if (otherEntity.linkedTo != null && otherEntity.linkedTo.Contains(this))
|
||||
{
|
||||
otherEntity.linkedTo.Remove(this);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
linkedTo.Add(otherEntity);
|
||||
if (otherEntity.Linkable && otherEntity.linkedTo != null) otherEntity.linkedTo.Add(this);
|
||||
if (otherEntity.Linkable && otherEntity.linkedTo != null)
|
||||
{
|
||||
otherEntity.linkedTo.Add(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1470,6 +1470,7 @@ namespace Barotrauma.Networking
|
||||
serverSettings.AllowFriendlyFire = inc.ReadBoolean();
|
||||
serverSettings.LockAllDefaultWires = inc.ReadBoolean();
|
||||
serverSettings.AllowRagdollButton = inc.ReadBoolean();
|
||||
serverSettings.AllowLinkingWifiToChat = inc.ReadBoolean();
|
||||
GameMain.NetLobbyScreen.UsingShuttle = inc.ReadBoolean();
|
||||
GameMain.LightManager.LosMode = (LosMode)inc.ReadByte();
|
||||
bool includesFinalize = inc.ReadBoolean(); inc.ReadPadBits();
|
||||
|
||||
@@ -92,9 +92,8 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientAdminRead(IReadMessage incMsg, NetFlags requiredFlags)
|
||||
public void ClientAdminRead(IReadMessage incMsg)
|
||||
{
|
||||
if (!requiredFlags.HasFlag(NetFlags.Properties)) { return; }
|
||||
int count = incMsg.ReadUInt16();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
@@ -162,7 +161,7 @@ namespace Barotrauma.Networking
|
||||
incMsg.ReadPadBits();
|
||||
if (isAdmin)
|
||||
{
|
||||
ClientAdminRead(incMsg, requiredFlags);
|
||||
ClientAdminRead(incMsg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,11 @@ namespace Barotrauma
|
||||
allowSubVoting = value;
|
||||
GameMain.NetLobbyScreen.SubList.Enabled = value ||
|
||||
(GameMain.Client != null && GameMain.Client.HasPermission(ClientPermissions.SelectSub));
|
||||
GameMain.NetLobbyScreen.Frame.FindChild("subvotes", true).Visible = value;
|
||||
var subVotesLabel = GameMain.NetLobbyScreen.Frame.FindChild("subvotes", true) as GUITextBlock;
|
||||
subVotesLabel.Visible = value;
|
||||
var subVisButton = GameMain.NetLobbyScreen.SubVisibilityButton;
|
||||
subVisButton.RectTransform.AbsoluteOffset
|
||||
= new Point(value ? (int)(subVotesLabel.TextSize.X + subVisButton.Rect.Width) : 0, 0);
|
||||
|
||||
UpdateVoteTexts(null, VoteType.Sub);
|
||||
GameMain.NetLobbyScreen.SubList.Deselect();
|
||||
|
||||
@@ -827,7 +827,8 @@ namespace Barotrauma
|
||||
TextManager.Get("Votes"), textAlignment: Alignment.CenterRight)
|
||||
{
|
||||
UserData = "subvotes",
|
||||
Visible = false
|
||||
Visible = false,
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
//respawn shuttle / submarine preview ------------------------------------------------------------------
|
||||
@@ -3435,9 +3436,12 @@ namespace Barotrauma
|
||||
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; }
|
||||
|
||||
private static bool StringsEqual(string a, string b)
|
||||
=> string.Equals(a, b, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
public static bool operator ==(FailedSubInfo a, FailedSubInfo b)
|
||||
=> a.Name.Equals(b.Name, StringComparison.OrdinalIgnoreCase)
|
||||
&& a.Hash.Equals(b.Hash, StringComparison.OrdinalIgnoreCase);
|
||||
=> StringsEqual(a.Name, b.Name) && StringsEqual(a.Hash, b.Hash);
|
||||
public static bool operator !=(FailedSubInfo a, FailedSubInfo b)
|
||||
=> !(a == b);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>0.15.17.0</Version>
|
||||
<Version>0.15.21.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>0.15.17.0</Version>
|
||||
<Version>0.15.21.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>0.15.17.0</Version>
|
||||
<Version>0.15.21.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>0.15.17.0</Version>
|
||||
<Version>0.15.21.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>0.15.17.0</Version>
|
||||
<Version>0.15.21.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
|
||||
@@ -404,7 +404,7 @@ namespace Barotrauma
|
||||
LastSaveID++;
|
||||
}
|
||||
|
||||
private void UpdateCampaignSubs()
|
||||
public static void UpdateCampaignSubs()
|
||||
{
|
||||
bool isSubmarineVisible(SubmarineInfo s)
|
||||
=> !GameMain.Server.ServerSettings.HiddenSubs.Any(h
|
||||
@@ -434,6 +434,9 @@ namespace Barotrauma
|
||||
GameMain.NetLobbyScreen.CampaignSubmarines = availableSubs;
|
||||
}
|
||||
|
||||
public bool CanPurchaseSub(SubmarineInfo info)
|
||||
=> info.Price <= Money && GameMain.NetLobbyScreen.CampaignSubmarines.Contains(info);
|
||||
|
||||
public void DiscardClientCharacterData(Client client)
|
||||
{
|
||||
characterData.RemoveAll(cd => cd.MatchesClient(client));
|
||||
|
||||
@@ -48,7 +48,6 @@ namespace Barotrauma.Items.Components
|
||||
msg.Write(tinkeringStrength);
|
||||
msg.Write(CurrentFixer == null ? (ushort)0 : CurrentFixer.ID);
|
||||
msg.WriteRangedInteger((int)currentFixerAction, 0, 2);
|
||||
msg.Write(repairBoost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,9 @@ namespace Barotrauma.Networking
|
||||
|
||||
public UInt16 LastRecvClientListUpdate = 0;
|
||||
|
||||
public UInt16 LastSentServerSettingsUpdate = 0;
|
||||
public UInt16 LastRecvServerSettingsUpdate = 0;
|
||||
|
||||
public UInt16 LastRecvLobbyUpdate = 0;
|
||||
|
||||
public UInt16 LastSentChatMsgID = 0; //last msg this client said
|
||||
|
||||
@@ -1036,6 +1036,11 @@ namespace Barotrauma.Networking
|
||||
case ClientNetObject.SYNC_IDS:
|
||||
//TODO: might want to use a clever class for this
|
||||
c.LastRecvLobbyUpdate = NetIdUtils.Clamp(inc.ReadUInt16(), c.LastRecvLobbyUpdate, GameMain.NetLobbyScreen.LastUpdateID);
|
||||
if (c.HasPermission(ClientPermissions.ManageSettings) &&
|
||||
NetIdUtils.IdMoreRecentOrMatches(c.LastRecvLobbyUpdate, c.LastSentServerSettingsUpdate))
|
||||
{
|
||||
c.LastRecvServerSettingsUpdate = c.LastSentServerSettingsUpdate;
|
||||
}
|
||||
c.LastRecvChatMsgID = NetIdUtils.Clamp(inc.ReadUInt16(), c.LastRecvChatMsgID, c.LastChatMsgQueueID);
|
||||
c.LastRecvClientListUpdate = NetIdUtils.Clamp(inc.ReadUInt16(), c.LastRecvClientListUpdate, LastClientListUpdateID);
|
||||
|
||||
@@ -2469,6 +2474,7 @@ namespace Barotrauma.Networking
|
||||
msg.Write(serverSettings.AllowFriendlyFire);
|
||||
msg.Write(serverSettings.LockAllDefaultWires);
|
||||
msg.Write(serverSettings.AllowRagdollButton);
|
||||
msg.Write(serverSettings.AllowLinkingWifiToChat);
|
||||
msg.Write(serverSettings.UseRespawnShuttle);
|
||||
msg.Write((byte)serverSettings.LosMode);
|
||||
msg.Write(includesFinalize); msg.WritePadBits();
|
||||
|
||||
@@ -15,13 +15,17 @@ namespace Barotrauma.Networking
|
||||
public static readonly char SubmarineSeparatorChar = '|';
|
||||
|
||||
public readonly Dictionary<NetFlags, UInt16> LastUpdateIdForFlag = new Dictionary<NetFlags, UInt16>();
|
||||
public UInt16 LastPropertyUpdateId { get; private set; } = 1;
|
||||
|
||||
public void UpdateFlag(NetFlags flag)
|
||||
=> LastUpdateIdForFlag[flag] = (UInt16)(GameMain.NetLobbyScreen.LastUpdateID + 1);
|
||||
|
||||
private bool IsFlagRequired(Client c, NetFlags flag)
|
||||
=> LastUpdateIdForFlag[flag] > c.LastRecvLobbyUpdate;
|
||||
|
||||
public NetFlags GetRequiredFlags(Client c)
|
||||
=> LastUpdateIdForFlag.Keys
|
||||
.Where(k => LastUpdateIdForFlag[k] > c.LastRecvLobbyUpdate)
|
||||
.Where(k => IsFlagRequired(c, k))
|
||||
.Concat(NetFlags.None.ToEnumerable()) //prevents InvalidOperationException in Aggregate
|
||||
.Aggregate((f1, f2) => f1 | f2);
|
||||
|
||||
@@ -43,14 +47,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
public void ServerAdminWrite(IWriteMessage outMsg, Client c)
|
||||
{
|
||||
//outMsg.Write(isPublic);
|
||||
//outMsg.Write(EnableUPnP);
|
||||
//outMsg.WritePadBits();
|
||||
//outMsg.Write((UInt16)QueryPort);
|
||||
|
||||
NetFlags requiredFlags = GetRequiredFlags(c);
|
||||
if (!requiredFlags.HasFlag(NetFlags.Properties)) { return; }
|
||||
|
||||
c.LastSentServerSettingsUpdate = LastPropertyUpdateId;
|
||||
WriteNetProperties(outMsg);
|
||||
WriteMonsterEnabled(outMsg);
|
||||
BanList.ServerAdminWrite(outMsg, c);
|
||||
@@ -85,7 +82,8 @@ namespace Barotrauma.Networking
|
||||
|
||||
WriteHiddenSubs(outMsg);
|
||||
|
||||
if (c.HasPermission(Networking.ClientPermissions.ManageSettings))
|
||||
if (c.HasPermission(Networking.ClientPermissions.ManageSettings)
|
||||
&& !NetIdUtils.IdMoreRecentOrMatches(c.LastRecvServerSettingsUpdate, LastPropertyUpdateId))
|
||||
{
|
||||
outMsg.Write(true);
|
||||
outMsg.WritePadBits();
|
||||
@@ -153,8 +151,12 @@ namespace Barotrauma.Networking
|
||||
if (changedMonsterSettings) { ReadMonsterEnabled(incMsg); }
|
||||
propertiesChanged |= BanList.ServerAdminRead(incMsg, c);
|
||||
propertiesChanged |= Whitelist.ServerAdminRead(incMsg, c);
|
||||
|
||||
if (propertiesChanged) { UpdateFlag(NetFlags.Properties); }
|
||||
|
||||
if (propertiesChanged)
|
||||
{
|
||||
UpdateFlag(NetFlags.Properties);
|
||||
LastPropertyUpdateId = (UInt16)(GameMain.NetLobbyScreen.LastUpdateID + 1);
|
||||
}
|
||||
changed |= propertiesChanged;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,10 +30,9 @@ namespace Barotrauma
|
||||
|
||||
public static SubmarineVote SubVote;
|
||||
|
||||
private void StartSubmarineVote(IReadMessage inc, VoteType voteType, Client sender)
|
||||
private void StartSubmarineVote(SubmarineInfo subInfo, VoteType voteType, Client sender)
|
||||
{
|
||||
string subName = inc.ReadString();
|
||||
SubVote.Sub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == subName);
|
||||
SubVote.Sub = subInfo;
|
||||
SubVote.DeliveryFee = voteType == VoteType.SwitchSub ? GameMain.GameSession.Map.DistanceToClosestLocationWithOutpost(GameMain.GameSession.Map.CurrentLocation, out Location endLocation) : 0;
|
||||
SubVote.VoteType = voteType;
|
||||
SubVote.State = VoteState.Started;
|
||||
@@ -130,7 +129,12 @@ namespace Barotrauma
|
||||
bool startVote = inc.ReadBoolean();
|
||||
if (startVote)
|
||||
{
|
||||
StartSubmarineVote(inc, voteType, sender);
|
||||
string subName = inc.ReadString();
|
||||
SubmarineInfo subInfo = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == subName);
|
||||
if (GameMain.GameSession?.Campaign is MultiPlayerCampaign campaign && campaign.CanPurchaseSub(subInfo))
|
||||
{
|
||||
StartSubmarineVote(subInfo, voteType, sender);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace Barotrauma
|
||||
set { selectedShuttle = value; lastUpdateID++; }
|
||||
}
|
||||
|
||||
[Obsolete("TODO: this list shouldn't exist, the client should just use the visible subs list instead")]
|
||||
public List<SubmarineInfo> CampaignSubmarines
|
||||
{
|
||||
get
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>0.15.17.0</Version>
|
||||
<Version>0.15.21.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
|
||||
@@ -726,6 +726,7 @@ namespace Barotrauma
|
||||
|
||||
if (!item.AllowedSlots.Contains(InvSlotType.Any) || !Character.Inventory.TryPutItem(item, Character, new List<InvSlotType>() { InvSlotType.Any }) && Character.Submarine?.TeamID == Character.TeamID )
|
||||
{
|
||||
if (item.AllowedSlots.Contains(InvSlotType.Bag) && Character.Inventory.TryPutItem(item, Character, new List<InvSlotType>() { InvSlotType.Bag })) { continue; }
|
||||
findItemState = FindItemState.OtherItem;
|
||||
if (FindSuitableContainer(item, out Item targetContainer))
|
||||
{
|
||||
@@ -877,8 +878,7 @@ namespace Barotrauma
|
||||
if (target.CurrentHull != hull || !target.Enabled) { continue; }
|
||||
if (AIObjectiveFightIntruders.IsValidTarget(target, Character))
|
||||
{
|
||||
bool arrested = AIObjectiveFightIntruders.ShouldArrest(target, Character) && target.HasEquippedItem("handlocker");
|
||||
if (!arrested && AddTargets<AIObjectiveFightIntruders, Character>(Character, target) && newOrder == null)
|
||||
if (!target.IsArrested && AddTargets<AIObjectiveFightIntruders, Character>(Character, target) && newOrder == null)
|
||||
{
|
||||
var orderPrefab = Order.GetPrefab("reportintruders");
|
||||
newOrder = new Order(orderPrefab, hull, null, orderGiver: Character);
|
||||
@@ -1871,7 +1871,7 @@ namespace Barotrauma
|
||||
float enemyFactor = 1;
|
||||
if (!ignoreEnemies)
|
||||
{
|
||||
bool isValidTarget(Character e) => IsActive(e) && !IsFriendly(character, e);
|
||||
bool isValidTarget(Character e) => IsActive(e) && !IsFriendly(character, e) && !e.IsArrested;
|
||||
int enemyCount = visibleHulls == null ?
|
||||
Character.CharacterList.Count(e => isValidTarget(e) && e.CurrentHull == hull) :
|
||||
Character.CharacterList.Count(e => isValidTarget(e) && visibleHulls.Contains(e.CurrentHull));
|
||||
|
||||
@@ -26,8 +26,9 @@ namespace Barotrauma
|
||||
|
||||
private float findPathTimer;
|
||||
|
||||
private const float buttonPressCooldown = 3;
|
||||
private float checkDoorsTimer;
|
||||
private float buttonPressCooldown;
|
||||
private float buttonPressTimer;
|
||||
|
||||
public SteeringPath CurrentPath
|
||||
{
|
||||
@@ -98,7 +99,7 @@ namespace Barotrauma
|
||||
base.Update(speed);
|
||||
float step = 1.0f / 60.0f;
|
||||
checkDoorsTimer -= step;
|
||||
buttonPressCooldown -= step;
|
||||
buttonPressTimer -= step;
|
||||
findPathTimer -= step;
|
||||
}
|
||||
|
||||
@@ -120,10 +121,18 @@ namespace Barotrauma
|
||||
{
|
||||
steering += base.DoSteeringSeek(targetSimPos, weight);
|
||||
}
|
||||
|
||||
|
||||
public void SteeringSeek(Vector2 target, float weight, float minGapWidth = 0, Func<PathNode, bool> startNodeFilter = null, Func<PathNode, bool> endNodeFilter = null, Func<PathNode, bool> nodeFilter = null, bool checkVisiblity = true)
|
||||
{
|
||||
steering += CalculateSteeringSeek(target, weight, minGapWidth, startNodeFilter, endNodeFilter, nodeFilter, checkVisiblity);
|
||||
if (buttonPressTimer > 0 && lastDoor.door != null && lastDoor.state && !lastDoor.door.IsOpen)
|
||||
{
|
||||
// We have pressed the button and are waiting for the door to open -> Hold still until we can press the button again.
|
||||
Reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
steering += CalculateSteeringSeek(target, weight, minGapWidth, startNodeFilter, endNodeFilter, nodeFilter, checkVisiblity);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -612,18 +621,17 @@ namespace Barotrauma
|
||||
float closestDist = 0;
|
||||
bool canAccess = CanAccessDoor(door, button =>
|
||||
{
|
||||
if (currentWaypoint == null) { return true; }
|
||||
// Check that the button is on the right side of the door. If the door is open, doesn't matter
|
||||
if (!door.IsOpen)
|
||||
// Check that the button is on the right side of the door.
|
||||
if (nextWaypoint != null)
|
||||
{
|
||||
if (door.LinkedGap.IsHorizontal)
|
||||
{
|
||||
int dir = Math.Sign((nextWaypoint ?? currentWaypoint).WorldPosition.X - door.Item.WorldPosition.X);
|
||||
int dir = Math.Sign((nextWaypoint).WorldPosition.X - door.Item.WorldPosition.X);
|
||||
if (button.Item.WorldPosition.X * dir > door.Item.WorldPosition.X * dir) { return false; }
|
||||
}
|
||||
else
|
||||
{
|
||||
int dir = Math.Sign((nextWaypoint ?? currentWaypoint).WorldPosition.Y - door.Item.WorldPosition.Y);
|
||||
int dir = Math.Sign((nextWaypoint).WorldPosition.Y - door.Item.WorldPosition.Y);
|
||||
if (button.Item.WorldPosition.Y * dir > door.Item.WorldPosition.Y * dir) { return false; }
|
||||
}
|
||||
}
|
||||
@@ -637,7 +645,7 @@ namespace Barotrauma
|
||||
});
|
||||
if (canAccess)
|
||||
{
|
||||
bool pressButton = buttonPressCooldown <= 0 || lastDoor.door != door || lastDoor.state != shouldBeOpen;
|
||||
bool pressButton = buttonPressTimer <= 0 || lastDoor.door != door || lastDoor.state != shouldBeOpen;
|
||||
if (door.HasIntegratedButtons)
|
||||
{
|
||||
if (pressButton && character.CanSeeTarget(door.Item))
|
||||
@@ -645,11 +653,11 @@ namespace Barotrauma
|
||||
if (door.Item.TryInteract(character, forceSelectKey: true))
|
||||
{
|
||||
lastDoor = (door, shouldBeOpen);
|
||||
buttonPressCooldown = 3;
|
||||
buttonPressTimer = buttonPressCooldown;
|
||||
}
|
||||
else
|
||||
{
|
||||
buttonPressCooldown = 0;
|
||||
buttonPressTimer = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -663,11 +671,11 @@ namespace Barotrauma
|
||||
if (closestButton.Item.TryInteract(character, forceSelectKey: true))
|
||||
{
|
||||
lastDoor = (door, shouldBeOpen);
|
||||
buttonPressCooldown = 3;
|
||||
buttonPressTimer = buttonPressCooldown;
|
||||
}
|
||||
else
|
||||
{
|
||||
buttonPressCooldown = 0;
|
||||
buttonPressTimer = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -111,7 +111,7 @@ namespace Barotrauma
|
||||
public CombatMode Mode { get; private set; }
|
||||
|
||||
private bool IsOffensiveOrArrest => initialMode == CombatMode.Offensive || initialMode == CombatMode.Arrest;
|
||||
private bool TargetEliminated => IsEnemyDisabled || Enemy.IsUnconscious && Enemy.Params.Health.ConstantHealthRegeneration <= 0.0f || Enemy.IsHuman && Enemy.HasEquippedItem("handlocker") && !character.IsInstigator;
|
||||
private bool TargetEliminated => IsEnemyDisabled || Enemy.IsUnconscious && Enemy.Params.Health.ConstantHealthRegeneration <= 0.0f || Enemy.IsArrested && !character.IsInstigator;
|
||||
private bool IsEnemyDisabled => Enemy == null || Enemy.Removed || Enemy.IsDead;
|
||||
|
||||
private float AimSpeed => HumanAIController.AimSpeed;
|
||||
@@ -668,6 +668,13 @@ namespace Barotrauma
|
||||
{
|
||||
if (!Weapon.AllowedSlots.Contains(InvSlotType.Any) || !character.Inventory.TryPutItem(Weapon, character, new List<InvSlotType>() { InvSlotType.Any }))
|
||||
{
|
||||
if (Weapon.AllowedSlots.Contains(InvSlotType.Bag))
|
||||
{
|
||||
if (character.Inventory.TryPutItem(Weapon, character, new List<InvSlotType>() { InvSlotType.Bag }))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
Weapon.Drop(character);
|
||||
}
|
||||
}
|
||||
@@ -680,10 +687,10 @@ namespace Barotrauma
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!character.HasEquippedItem(Weapon))
|
||||
if (!character.HasEquippedItem(Weapon, predicate: IsHandSlotType))
|
||||
{
|
||||
Weapon.TryInteract(character, forceSelectKey: true);
|
||||
var slots = Weapon.AllowedSlots.Where(s => s == InvSlotType.LeftHand || s == InvSlotType.RightHand || s == (InvSlotType.LeftHand | InvSlotType.RightHand));
|
||||
var slots = Weapon.AllowedSlots.Where(s => IsHandSlotType(s));
|
||||
if (character.Inventory.TryPutItem(Weapon, character, slots))
|
||||
{
|
||||
aimTimer = Rand.Range(0.2f, 0.4f) / AimSpeed;
|
||||
@@ -697,6 +704,8 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
bool IsHandSlotType(InvSlotType s) => s == InvSlotType.LeftHand || s == InvSlotType.RightHand || s == (InvSlotType.LeftHand | InvSlotType.RightHand);
|
||||
}
|
||||
|
||||
private float findHullTimer;
|
||||
@@ -903,8 +912,9 @@ namespace Barotrauma
|
||||
TryAddSubObjective(ref seekAmmunitionObjective,
|
||||
constructor: () => new AIObjectiveContainItem(character, ammunitionIdentifiers, Weapon.GetComponent<ItemContainer>(), objectiveManager)
|
||||
{
|
||||
ItemCount = Weapon.GetComponent<ItemContainer>().Capacity,
|
||||
checkInventory = false
|
||||
ItemCount = Weapon.GetComponent<ItemContainer>().Capacity * Weapon.GetComponent<ItemContainer>().MaxStackSize,
|
||||
checkInventory = false,
|
||||
MoveWholeStack = true
|
||||
},
|
||||
onCompleted: () => RemoveSubObjective(ref seekAmmunitionObjective),
|
||||
onAbandon: () =>
|
||||
|
||||
@@ -186,7 +186,9 @@ namespace Barotrauma
|
||||
AllowToFindDivingGear = AllowToFindDivingGear,
|
||||
AllowDangerousPressure = AllowDangerousPressure,
|
||||
TargetCondition = ConditionLevel,
|
||||
ItemFilter = (Item potentialItem) => RemoveEmpty ? container.CanBeContained(potentialItem) : container.Inventory.CanBePut(potentialItem)
|
||||
ItemFilter = (Item potentialItem) => RemoveEmpty ? container.CanBeContained(potentialItem) : container.Inventory.CanBePut(potentialItem),
|
||||
ItemCount = ItemCount,
|
||||
TakeWholeStack = MoveWholeStack
|
||||
}, onAbandon: () =>
|
||||
{
|
||||
Abandon = true;
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace Barotrauma
|
||||
if (HumanAIController.IsFriendly(character, target)) { return false; }
|
||||
if (!character.Submarine.IsConnectedTo(target.Submarine)) { return false; }
|
||||
if (target.HasAbilityFlag(AbilityFlags.IgnoredByEnemyAI)) { return false; }
|
||||
if (ShouldArrest(target, character) && target.HasEquippedItem("handlocker")) { return false; }
|
||||
if (target.IsArrested) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -262,7 +262,7 @@ namespace Barotrauma
|
||||
}
|
||||
foreach (Character enemy in Character.CharacterList)
|
||||
{
|
||||
if (!HumanAIController.IsActive(enemy) || HumanAIController.IsFriendly(enemy)) { continue; }
|
||||
if (!HumanAIController.IsActive(enemy) || HumanAIController.IsFriendly(enemy) || enemy.IsArrested) { continue; }
|
||||
if (HumanAIController.VisibleHulls.Contains(enemy.CurrentHull))
|
||||
{
|
||||
Vector2 dir = character.Position - enemy.Position;
|
||||
|
||||
@@ -182,8 +182,12 @@ namespace Barotrauma
|
||||
{
|
||||
if (character.SelectedConstruction != Item)
|
||||
{
|
||||
if (!Item.TryInteract(character, ignoreRequiredItems: true, forceSelectKey: true) &&
|
||||
!Item.TryInteract(character, ignoreRequiredItems: true, forceUseKey: true))
|
||||
if (Item.TryInteract(character, ignoreRequiredItems: true, forceSelectKey: true) ||
|
||||
Item.TryInteract(character, ignoreRequiredItems: true, forceUseKey: true))
|
||||
{
|
||||
character.SelectedConstruction = Item;
|
||||
}
|
||||
else
|
||||
{
|
||||
Abandon = true;
|
||||
}
|
||||
|
||||
@@ -199,7 +199,7 @@ namespace Barotrauma
|
||||
|
||||
foreach (Character potentialCharacter in Character.CharacterList)
|
||||
{
|
||||
if (!HumanAIController.IsActive(character)) { continue; }
|
||||
if (!HumanAIController.IsActive(potentialCharacter)) { continue; }
|
||||
|
||||
if (HumanAIController.IsFriendly(character, potentialCharacter, true) && potentialCharacter.AIController is HumanAIController)
|
||||
{
|
||||
|
||||
@@ -621,6 +621,11 @@ namespace Barotrauma
|
||||
get { return CharacterHealth.IsUnconscious; }
|
||||
}
|
||||
|
||||
public bool IsArrested
|
||||
{
|
||||
get { return IsHuman && HasEquippedItem("handlocker"); }
|
||||
}
|
||||
|
||||
public bool IsPet
|
||||
{
|
||||
get { return AIController is EnemyAIController enemyController && enemyController.PetBehavior != null; }
|
||||
@@ -2043,16 +2048,21 @@ namespace Barotrauma
|
||||
|
||||
public bool HasItem(Item item, bool requireEquipped = false, InvSlotType? slotType = null) => requireEquipped ? HasEquippedItem(item, slotType) : item.IsOwnedBy(this);
|
||||
|
||||
public bool HasEquippedItem(Item item, InvSlotType? slotType = null)
|
||||
public bool HasEquippedItem(Item item, InvSlotType? slotType = null, Func<InvSlotType, bool> predicate = null)
|
||||
{
|
||||
if (Inventory == null) { return false; }
|
||||
for (int i = 0; i < Inventory.Capacity; i++)
|
||||
{
|
||||
InvSlotType slot = Inventory.SlotTypes[i];
|
||||
if (predicate != null)
|
||||
{
|
||||
if (!predicate(slot)) { continue; }
|
||||
}
|
||||
if (slotType.HasValue)
|
||||
{
|
||||
if (!slotType.Value.HasFlag(Inventory.SlotTypes[i])) { continue; }
|
||||
if (!slotType.Value.HasFlag(slot)) { continue; }
|
||||
}
|
||||
else if (Inventory.SlotTypes[i] == InvSlotType.Any)
|
||||
else if (slot == InvSlotType.Any)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1206,7 +1206,7 @@ namespace Barotrauma
|
||||
return (int)(salary * Job.Prefab.PriceMultiplier);
|
||||
}
|
||||
|
||||
public void IncreaseSkillLevel(string skillIdentifier, float increase, bool gainedFromApprenticeship = false)
|
||||
public void IncreaseSkillLevel(string skillIdentifier, float increase, bool gainedFromAbility = false)
|
||||
{
|
||||
if (Job == null || (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) || Character == null) { return; }
|
||||
|
||||
@@ -1226,7 +1226,7 @@ namespace Barotrauma
|
||||
{
|
||||
// assume we are getting at least 1 point in skill, since this logic only runs in such cases
|
||||
float increaseSinceLastSkillPoint = MathHelper.Max(increase, 1f);
|
||||
var abilitySkillGain = new AbilitySkillGain(increaseSinceLastSkillPoint, skillIdentifier, Character, gainedFromApprenticeship);
|
||||
var abilitySkillGain = new AbilitySkillGain(increaseSinceLastSkillPoint, skillIdentifier, Character, gainedFromAbility);
|
||||
Character.CheckTalents(AbilityEffectType.OnGainSkillPoint, abilitySkillGain);
|
||||
foreach (Character character in Character.GetFriendlyCrew(Character))
|
||||
{
|
||||
@@ -1298,9 +1298,9 @@ namespace Barotrauma
|
||||
return Math.Max(GetTotalTalentPoints() - GetUnlockedTalentsInTree().Count(), 0);
|
||||
}
|
||||
|
||||
public int GetProgressTowardsNextLevel()
|
||||
public float GetProgressTowardsNextLevel()
|
||||
{
|
||||
return (ExperiencePoints - GetExperienceRequiredForCurrentLevel()) / (GetExperienceRequiredToLevelUp() - GetExperienceRequiredForCurrentLevel());
|
||||
return (ExperiencePoints - GetExperienceRequiredForCurrentLevel()) / (float)(GetExperienceRequiredToLevelUp() - GetExperienceRequiredForCurrentLevel());
|
||||
}
|
||||
|
||||
public int GetExperienceRequiredForCurrentLevel()
|
||||
@@ -1860,16 +1860,16 @@ namespace Barotrauma
|
||||
|
||||
class AbilitySkillGain : AbilityObject, IAbilityValue, IAbilityString, IAbilityCharacter
|
||||
{
|
||||
public AbilitySkillGain(float value, string abilityString, Character character, bool gainedFromApprenticeship)
|
||||
public AbilitySkillGain(float value, string abilityString, Character character, bool gainedFromAbility)
|
||||
{
|
||||
Value = value;
|
||||
String = abilityString;
|
||||
Character = character;
|
||||
GainedFromApprenticeship = gainedFromApprenticeship;
|
||||
GainedFromAbility = gainedFromAbility;
|
||||
}
|
||||
public Character Character { get; set; }
|
||||
public float Value { get; set; }
|
||||
public string String { get; set; }
|
||||
public bool GainedFromApprenticeship { get; set; }
|
||||
public bool GainedFromAbility { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -959,14 +959,11 @@ namespace Barotrauma
|
||||
{
|
||||
var affliction = kvp.Key;
|
||||
var limbHealth = kvp.Value;
|
||||
if (limb != null)
|
||||
if (limb != null && affliction.Prefab.IndicatorLimb != limb.type)
|
||||
{
|
||||
if (limbHealth == null) { continue; }
|
||||
int healthIndex = limbHealths.IndexOf(limbHealth);
|
||||
Limb targetLimb =
|
||||
Character.AnimController.Limbs.LastOrDefault(l => !l.IsSevered && !l.Hidden && l.HealthIndex == healthIndex) ??
|
||||
Character.AnimController.MainLimb;
|
||||
if (limb != targetLimb) { continue; }
|
||||
if (limb.HealthIndex != healthIndex) { continue; }
|
||||
}
|
||||
|
||||
float strength = affliction.Strength;
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Barotrauma
|
||||
public string Identifier { get; }
|
||||
|
||||
public const float MaximumSkill = 100.0f;
|
||||
|
||||
|
||||
public float Level
|
||||
{
|
||||
get { return level; }
|
||||
@@ -18,7 +18,7 @@ namespace Barotrauma
|
||||
|
||||
public void IncreaseSkill(float value, bool increasePastMax)
|
||||
{
|
||||
level = MathHelper.Clamp(level + value, 0.0f, increasePastMax ? float.MaxValue : MaximumSkill);
|
||||
level = MathHelper.Clamp(level + value, 0.0f, increasePastMax ? SkillSettings.Current.MaximumOlympianSkill : MaximumSkill);
|
||||
}
|
||||
|
||||
private Sprite icon;
|
||||
|
||||
@@ -96,6 +96,13 @@ namespace Barotrauma
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(500.0f, true)]
|
||||
public float MaximumOlympianSkill
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
private SkillSettings(XElement element)
|
||||
{
|
||||
SerializableProperties = SerializableProperty.DeserializeProperties(this, element);
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Barotrauma.Abilities
|
||||
private readonly bool ignoreNonHarmfulAttacks;
|
||||
public AbilityConditionAttackData(CharacterTalent characterTalent, XElement conditionElement) : base(characterTalent, conditionElement)
|
||||
{
|
||||
itemIdentifier = conditionElement.GetAttributeString("itemidentifier", "");
|
||||
itemIdentifier = conditionElement.GetAttributeString("itemidentifier", string.Empty);
|
||||
tags = conditionElement.GetAttributeStringArray("tags", new string[0], convertToLowerInvariant: true);
|
||||
ignoreNonHarmfulAttacks = conditionElement.GetAttributeBool("ignorenonharmfulattacks", false);
|
||||
|
||||
@@ -46,15 +46,10 @@ namespace Barotrauma.Abilities
|
||||
}
|
||||
|
||||
Item item = attackData?.SourceAttack?.SourceItem;
|
||||
if (item == null)
|
||||
{
|
||||
DebugConsole.AddWarning($"Source Item was not found in {this} for talent {characterTalent.DebugIdentifier}!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(itemIdentifier))
|
||||
{
|
||||
if (item.prefab.Identifier != itemIdentifier)
|
||||
if (item?.prefab.Identifier != itemIdentifier)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -62,31 +57,34 @@ namespace Barotrauma.Abilities
|
||||
|
||||
if (tags.Any())
|
||||
{
|
||||
if (!tags.All(t => item.HasTag(t)))
|
||||
if (!tags.All(t => item?.HasTag(t) ?? false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
switch (weapontype)
|
||||
if (weapontype != WeaponType.Any)
|
||||
{
|
||||
// it is possible that an item that has both a melee and a projectile component will return true
|
||||
// even when not used as a melee/ranged weapon respectively
|
||||
// attackdata should contain data regarding whether the attack is melee or not
|
||||
case WeaponType.Melee:
|
||||
return item.GetComponent<MeleeWeapon>() != null;
|
||||
case WeaponType.Ranged:
|
||||
return item.GetComponent<Projectile>() != null;
|
||||
case WeaponType.HandheldRanged:
|
||||
{
|
||||
var projectile = item.GetComponent<Projectile>();
|
||||
return projectile?.Launcher?.GetComponent<Holdable>() != null;
|
||||
}
|
||||
case WeaponType.Turret:
|
||||
{
|
||||
var projectile = item.GetComponent<Projectile>();
|
||||
return projectile?.Launcher?.GetComponent<Turret>() != null;
|
||||
}
|
||||
switch (weapontype)
|
||||
{
|
||||
// it is possible that an item that has both a melee and a projectile component will return true
|
||||
// even when not used as a melee/ranged weapon respectively
|
||||
// attackdata should contain data regarding whether the attack is melee or not
|
||||
case WeaponType.Melee:
|
||||
return item?.GetComponent<MeleeWeapon>() != null;
|
||||
case WeaponType.Ranged:
|
||||
return item?.GetComponent<Projectile>() != null;
|
||||
case WeaponType.HandheldRanged:
|
||||
{
|
||||
var projectile = item?.GetComponent<Projectile>();
|
||||
return projectile?.Launcher?.GetComponent<Holdable>() != null;
|
||||
}
|
||||
case WeaponType.Turret:
|
||||
{
|
||||
var projectile = item?.GetComponent<Projectile>();
|
||||
return projectile?.Launcher?.GetComponent<Turret>() != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -5,18 +5,21 @@ namespace Barotrauma.Abilities
|
||||
{
|
||||
class CharacterAbilityGainSimultaneousSkill : CharacterAbility
|
||||
{
|
||||
private string skillIdentifier;
|
||||
private readonly string skillIdentifier;
|
||||
private readonly bool ignoreAbilitySkillGain;
|
||||
|
||||
public CharacterAbilityGainSimultaneousSkill(CharacterAbilityGroup characterAbilityGroup, XElement abilityElement) : base(characterAbilityGroup, abilityElement)
|
||||
{
|
||||
skillIdentifier = abilityElement.GetAttributeString("skillidentifier", "").ToLowerInvariant();
|
||||
ignoreAbilitySkillGain = abilityElement.GetAttributeBool("ignoreabilityskillgain", true);
|
||||
}
|
||||
|
||||
protected override void ApplyEffect(AbilityObject abilityObject)
|
||||
{
|
||||
if ((abilityObject as IAbilityValue)?.Value is float skillIncrease)
|
||||
if (abilityObject is AbilitySkillGain abilitySkillGain)
|
||||
{
|
||||
Character.Info?.IncreaseSkillLevel(skillIdentifier, skillIncrease);
|
||||
if (ignoreAbilitySkillGain && !abilitySkillGain.GainedFromAbility) { return; }
|
||||
Character.Info?.IncreaseSkillLevel(skillIdentifier, abilitySkillGain.Value, gainedFromAbility: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -49,11 +49,11 @@ namespace Barotrauma.Abilities
|
||||
{
|
||||
var skill = character.Info?.Job?.Skills?.GetRandom();
|
||||
if (skill == null) { return; }
|
||||
character.Info?.IncreaseSkillLevel(skill.Identifier, skillIncrease);
|
||||
character.Info?.IncreaseSkillLevel(skill.Identifier, skillIncrease, gainedFromAbility: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
character.Info?.IncreaseSkillLevel(skillIdentifier, skillIncrease);
|
||||
character.Info?.IncreaseSkillLevel(skillIdentifier, skillIncrease, gainedFromAbility: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Abilities
|
||||
{
|
||||
class CharacterAbilityModifyReduceAffliction : CharacterAbility
|
||||
{
|
||||
float addedAmountMultiplier;
|
||||
public override bool AllowClientSimulation => true;
|
||||
|
||||
public CharacterAbilityModifyReduceAffliction(CharacterAbilityGroup characterAbilityGroup, XElement abilityElement) : base(characterAbilityGroup, abilityElement)
|
||||
{
|
||||
addedAmountMultiplier = abilityElement.GetAttributeFloat("addedamountmultiplier", 0f);
|
||||
}
|
||||
|
||||
protected override void ApplyEffect(AbilityObject abilityObject)
|
||||
{
|
||||
if (abilityObject is AbilityValueAffliction afflictionReduceAmount)
|
||||
{
|
||||
afflictionReduceAmount.Affliction.Strength -= addedAmountMultiplier * afflictionReduceAmount.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogabilityObjectMismatch();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@ namespace Barotrauma.Abilities
|
||||
if (GameMain.GameSession?.RoundEnding ?? true)
|
||||
{
|
||||
Item item = new Item(itemPrefab, Character.WorldPosition, Character.Submarine);
|
||||
if (!Character.Inventory.TryPutItem(item, Character))
|
||||
if (!Character.Inventory.TryPutItem(item, Character, item.AllowedSlots))
|
||||
{
|
||||
foreach (Item containedItem in Character.Inventory.AllItemsMod)
|
||||
{
|
||||
|
||||
@@ -6,15 +6,19 @@ namespace Barotrauma.Abilities
|
||||
{
|
||||
class CharacterAbilityApprenticeship : CharacterAbility
|
||||
{
|
||||
private readonly bool ignoreAbilitySkillGain;
|
||||
|
||||
public CharacterAbilityApprenticeship(CharacterAbilityGroup characterAbilityGroup, XElement abilityElement) : base(characterAbilityGroup, abilityElement)
|
||||
{
|
||||
ignoreAbilitySkillGain = abilityElement.GetAttributeBool("ignoreabilityskillgain", true);
|
||||
}
|
||||
|
||||
protected override void ApplyEffect(AbilityObject abilityObject)
|
||||
{
|
||||
if (abilityObject is AbilitySkillGain abilitySkillGain && !abilitySkillGain.GainedFromApprenticeship && abilitySkillGain.Character != Character)
|
||||
if (abilityObject is AbilitySkillGain abilitySkillGain && abilitySkillGain.Character != Character)
|
||||
{
|
||||
Character.Info?.IncreaseSkillLevel(abilitySkillGain.String, 1.0f, gainedFromApprenticeship: true);
|
||||
if (ignoreAbilitySkillGain && !abilitySkillGain.GainedFromAbility) { return; }
|
||||
Character.Info?.IncreaseSkillLevel(abilitySkillGain.String, 1.0f, gainedFromAbility: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Barotrauma.Abilities
|
||||
if (skillIdentifier != lastSkillIdentifier)
|
||||
{
|
||||
lastSkillIdentifier = skillIdentifier;
|
||||
Character.Info?.IncreaseSkillLevel(skillIdentifier, 1.0f);
|
||||
Character.Info?.IncreaseSkillLevel(skillIdentifier, 1.0f, gainedFromAbility: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1531,6 +1531,11 @@ namespace Barotrauma
|
||||
}
|
||||
}, isCheat: true));
|
||||
|
||||
commands.Add(new Command("skipeventcooldown", "skipeventcooldown: Skips the currently active event cooldown and triggers pending monster spawns immediately.", args =>
|
||||
{
|
||||
GameMain.GameSession?.EventManager?.SkipEventCooldown();
|
||||
}, isCheat: true));
|
||||
|
||||
commands.Add(new Command("ballastflora", "infectballast [options]: Infect ballasts and control its growth.", args =>
|
||||
{
|
||||
if (args.Length == 0)
|
||||
|
||||
@@ -149,12 +149,12 @@ namespace Barotrauma
|
||||
}
|
||||
MTRandom rand = new MTRandom(seed);
|
||||
|
||||
EventSet initialEventSet = SelectRandomEvents(EventSet.List, rand);
|
||||
EventSet initialEventSet = SelectRandomEvents(EventSet.List, requireCampaignSet: GameMain.GameSession?.GameMode is CampaignMode, rand);
|
||||
EventSet additiveSet = null;
|
||||
if (initialEventSet != null && initialEventSet.Additive)
|
||||
{
|
||||
additiveSet = initialEventSet;
|
||||
initialEventSet = SelectRandomEvents(EventSet.List.FindAll(e => !e.Additive), rand);
|
||||
initialEventSet = SelectRandomEvents(EventSet.List.FindAll(e => !e.Additive), requireCampaignSet: GameMain.GameSession?.GameMode is CampaignMode, rand);
|
||||
}
|
||||
if (initialEventSet != null)
|
||||
{
|
||||
@@ -418,6 +418,11 @@ namespace Barotrauma
|
||||
pathFinder = null;
|
||||
}
|
||||
|
||||
public void SkipEventCooldown()
|
||||
{
|
||||
eventCoolDown = 0.0f;
|
||||
}
|
||||
|
||||
private float CalculateCommonness(EventPrefab eventPrefab, float baseCommonness)
|
||||
{
|
||||
if (level.LevelData.NonRepeatableEvents.Contains(eventPrefab)) { return 0.0f; }
|
||||
@@ -500,7 +505,7 @@ namespace Barotrauma
|
||||
}
|
||||
if (eventSet.ChildSets.Count > 0)
|
||||
{
|
||||
var newEventSet = SelectRandomEvents(eventSet.ChildSets, rand);
|
||||
var newEventSet = SelectRandomEvents(eventSet.ChildSets, random: rand);
|
||||
if (newEventSet != null)
|
||||
{
|
||||
CreateEvents(newEventSet, rand);
|
||||
@@ -535,18 +540,38 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private EventSet SelectRandomEvents(List<EventSet> eventSets, Random random = null)
|
||||
private EventSet SelectRandomEvents(List<EventSet> eventSets, bool? requireCampaignSet = null, Random random = null)
|
||||
{
|
||||
if (level == null) { return null; }
|
||||
Random rand = random ?? new MTRandom(ToolBox.StringToInt(level.Seed));
|
||||
|
||||
var allowedEventSets =
|
||||
eventSets.Where(es =>
|
||||
es.IsCampaignSet == GameMain.GameSession?.GameMode is CampaignMode &&
|
||||
level.Difficulty >= es.MinLevelDifficulty && level.Difficulty <= es.MaxLevelDifficulty &&
|
||||
level.LevelData.Type == es.LevelType &&
|
||||
(string.IsNullOrEmpty(es.BiomeIdentifier) || es.BiomeIdentifier.Equals(level.LevelData.Biome.Identifier, StringComparison.OrdinalIgnoreCase)));
|
||||
|
||||
if (requireCampaignSet.HasValue)
|
||||
{
|
||||
if (requireCampaignSet.Value)
|
||||
{
|
||||
if (allowedEventSets.Any(es => es.IsCampaignSet))
|
||||
{
|
||||
allowedEventSets =
|
||||
allowedEventSets.Where(es => es.IsCampaignSet);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.AddWarning("No campaign event sets available. Using a non-campaign-specific set instead.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
allowedEventSets =
|
||||
allowedEventSets.Where(es => !es.IsCampaignSet);
|
||||
}
|
||||
}
|
||||
|
||||
Location location = (GameMain.GameSession?.GameMode as CampaignMode)?.Map?.CurrentLocation ?? level?.StartLocation;
|
||||
LocationType locationType = location?.GetLocationType();
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ namespace Barotrauma
|
||||
DelayWhenCrewAway = element.GetAttributeBool("delaywhencrewaway", !PerRuin && !PerCave && !PerWreck);
|
||||
OncePerOutpost = element.GetAttributeBool("onceperoutpost", false);
|
||||
TriggerEventCooldown = element.GetAttributeBool("triggereventcooldown", true);
|
||||
IsCampaignSet = element.GetAttributeBool("campaign", LevelType == LevelData.LevelType.Outpost);
|
||||
IsCampaignSet = element.GetAttributeBool("campaign", LevelType == LevelData.LevelType.Outpost || (parentSet?.IsCampaignSet ?? false));
|
||||
|
||||
Commonness[""] = element.GetAttributeFloat("commonness", 1.0f);
|
||||
foreach (XElement subElement in element.Elements())
|
||||
|
||||
@@ -42,15 +42,15 @@ namespace Barotrauma
|
||||
{
|
||||
if (maxAmount <= 1)
|
||||
{
|
||||
return "MonsterEvent (" + speciesName + ")";
|
||||
return $"MonsterEvent ({speciesName}, {SpawnPosType})";
|
||||
}
|
||||
else if (minAmount < maxAmount)
|
||||
{
|
||||
return "MonsterEvent (" + speciesName + " x" + minAmount + "-" + maxAmount + ")";
|
||||
return $"MonsterEvent ({speciesName} x{minAmount}-{maxAmount}, {SpawnPosType})";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "MonsterEvent (" + speciesName + " x" + maxAmount + ")";
|
||||
return $"MonsterEvent ({speciesName} x{maxAmount}, {SpawnPosType})";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -317,9 +317,11 @@ namespace Barotrauma
|
||||
#endif
|
||||
|
||||
string exePath = Assembly.GetEntryAssembly()!.Location;
|
||||
string? exeName = null;
|
||||
string? exeName = string.Empty;
|
||||
#if SERVER
|
||||
exeName = "s";
|
||||
#endif
|
||||
Md5Hash? exeHash = null;
|
||||
exeName = Path.GetFileNameWithoutExtension(exePath).Replace(":", "");
|
||||
try
|
||||
{
|
||||
using (var stream = File.OpenRead(exePath))
|
||||
@@ -333,16 +335,27 @@ namespace Barotrauma
|
||||
}
|
||||
try
|
||||
{
|
||||
string buildConfiguration = "Release";
|
||||
#if DEBUG
|
||||
buildConfiguration = "Debug";
|
||||
#elif UNSTABLE
|
||||
buildConfiguration = "Unstable";
|
||||
#endif
|
||||
loadedImplementation?.ConfigureBuild(GameMain.Version.ToString()
|
||||
+ (string.IsNullOrEmpty(exeName) ? "Unknown" : exeName) + ":"
|
||||
+ ((exeHash?.ShortHash == null) ? "Unknown" : exeHash.ShortHash));
|
||||
+ exeName + ":"
|
||||
+ AssemblyInfo.GitRevision + ":"
|
||||
+ buildConfiguration);
|
||||
loadedImplementation?.ConfigureAvailableCustomDimensions01("singleplayer", "multiplayer", "editor");
|
||||
|
||||
InitKeys();
|
||||
|
||||
loadedImplementation?.AddDesignEvent("Executable:"
|
||||
+ (string.IsNullOrEmpty(exeName) ? "Unknown" : exeName) + ":"
|
||||
+ ((exeHash?.ShortHash == null) ? "Unknown" : exeHash.ShortHash));
|
||||
+ GameMain.Version.ToString()
|
||||
+ exeName + ":"
|
||||
+ ((exeHash?.ShortHash == null) ? "Unknown" : exeHash.ShortHash) + ":"
|
||||
+ AssemblyInfo.GitBranch + ":"
|
||||
+ AssemblyInfo.GitRevision + ":"
|
||||
+ buildConfiguration);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
using GameAnalyticsSDK.Net;
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using Barotrauma.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public static class GameAnalyticsManager
|
||||
{
|
||||
private static HashSet<string> sentEventIdentifiers = new HashSet<string>();
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
#if DEBUG
|
||||
try
|
||||
{
|
||||
GameAnalytics.SetEnabledInfoLog(true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Initializing GameAnalytics failed. Disabling user statistics...", e);
|
||||
GameSettings.SendUserStatistics = false;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
string exePath = Assembly.GetEntryAssembly().Location;
|
||||
string exeName = null;
|
||||
Md5Hash exeHash = null;
|
||||
exeName = Path.GetFileNameWithoutExtension(exePath).Replace(":", "");
|
||||
var md5 = MD5.Create();
|
||||
try
|
||||
{
|
||||
using (var stream = File.OpenRead(exePath))
|
||||
{
|
||||
exeHash = new Md5Hash(stream);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Error while calculating MD5 hash for the executable \"" + exePath + "\"", e);
|
||||
}
|
||||
try
|
||||
{
|
||||
GameAnalytics.ConfigureBuild(GameMain.Version.ToString()
|
||||
+ (string.IsNullOrEmpty(exeName) ? "Unknown" : exeName) + ":"
|
||||
+ ((exeHash?.ShortHash == null) ? "Unknown" : exeHash.ShortHash));
|
||||
GameAnalytics.ConfigureAvailableCustomDimensions01("singleplayer", "multiplayer", "editor");
|
||||
|
||||
GameAnalytics.Initialize("a3a073c20982de7c15d21e840e149122", "9010ad9a671233b8d9610d76cec8c897d9ff3ba7");
|
||||
|
||||
GameAnalytics.AddDesignEvent("Executable:"
|
||||
+ (string.IsNullOrEmpty(exeName) ? "Unknown" : exeName) + ":"
|
||||
+ ((exeHash?.ShortHash == null) ? "Unknown" : exeHash.ShortHash));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Initializing GameAnalytics failed. Disabling user statistics...", e);
|
||||
GameSettings.SendUserStatistics = false;
|
||||
return;
|
||||
}
|
||||
|
||||
var allPackages = GameMain.Config?.AllEnabledPackages.ToList();
|
||||
if (allPackages?.Count > 0)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder("ContentPackage: ");
|
||||
int i = 0;
|
||||
foreach (ContentPackage cp in allPackages)
|
||||
{
|
||||
string trimmedName = cp.Name.Replace(":", "").Replace(" ", "");
|
||||
sb.Append(trimmedName.Substring(0, Math.Min(32, trimmedName.Length)));
|
||||
if (i < allPackages.Count - 1) { sb.Append(" "); }
|
||||
}
|
||||
GameAnalytics.AddDesignEvent(sb.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an error event to GameAnalytics if an event with the same identifier has not been added yet.
|
||||
/// </summary>
|
||||
public static void AddErrorEventOnce(string identifier, EGAErrorSeverity errorSeverity, string message)
|
||||
{
|
||||
if (!GameSettings.SendUserStatistics) { return; }
|
||||
if (sentEventIdentifiers.Contains(identifier)) { return; }
|
||||
|
||||
if (GameMain.Config.AllEnabledPackages != null)
|
||||
{
|
||||
if (GameMain.VanillaContent == null || GameMain.Config.AllEnabledPackages.Any(p => p.HasMultiplayerIncompatibleContent && p != GameMain.VanillaContent))
|
||||
{
|
||||
message = "[MODDED] " + message;
|
||||
}
|
||||
}
|
||||
|
||||
GameAnalytics.AddErrorEvent(errorSeverity, message);
|
||||
sentEventIdentifiers.Add(identifier);
|
||||
}
|
||||
|
||||
public static void AddDesignEvent(string eventID)
|
||||
{
|
||||
if (!GameSettings.SendUserStatistics) return;
|
||||
GameAnalytics.AddDesignEvent(eventID);
|
||||
}
|
||||
|
||||
public static void AddDesignEvent(string eventID, double value)
|
||||
{
|
||||
if (!GameSettings.SendUserStatistics) return;
|
||||
GameAnalytics.AddDesignEvent(eventID, value);
|
||||
}
|
||||
|
||||
public static void AddProgressionEvent(EGAProgressionStatus progressionStatus, string progression01)
|
||||
{
|
||||
if (!GameSettings.SendUserStatistics) return;
|
||||
GameAnalytics.AddProgressionEvent(progressionStatus, progression01);
|
||||
}
|
||||
|
||||
public static void AddProgressionEvent(EGAProgressionStatus progressionStatus, string progression01, string progression02)
|
||||
{
|
||||
if (!GameSettings.SendUserStatistics) return;
|
||||
GameAnalytics.AddProgressionEvent(progressionStatus, progression01, progression02);
|
||||
}
|
||||
|
||||
public static void SetCustomDimension01(string dimension)
|
||||
{
|
||||
if (!GameSettings.SendUserStatistics) return;
|
||||
GameAnalytics.SetCustomDimension01(dimension);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -283,7 +283,8 @@ namespace Barotrauma
|
||||
|
||||
public void PurchaseSubmarine(SubmarineInfo newSubmarine)
|
||||
{
|
||||
if (Campaign == null) return;
|
||||
if (Campaign is null) { return; }
|
||||
if (Campaign.Money < newSubmarine.Price) { return; }
|
||||
if (!OwnedSubmarines.Any(s => s.Name == newSubmarine.Name))
|
||||
{
|
||||
Campaign.Money -= newSubmarine.Price;
|
||||
|
||||
@@ -207,8 +207,14 @@ namespace Barotrauma.Items.Components
|
||||
if (!item.linkedTo.Contains(target.item)) { item.linkedTo.Add(target.item); }
|
||||
if (!target.item.linkedTo.Contains(item)) { target.item.linkedTo.Add(item); }
|
||||
|
||||
if (!target.item.Submarine.DockedTo.Contains(item.Submarine)) target.item.Submarine.ConnectedDockingPorts.Add(item.Submarine, target);
|
||||
if (!item.Submarine.DockedTo.Contains(target.item.Submarine)) item.Submarine.ConnectedDockingPorts.Add(target.item.Submarine, this);
|
||||
if (!target.item.Submarine.DockedTo.Contains(item.Submarine))
|
||||
{
|
||||
target.item.Submarine.ConnectedDockingPorts.Add(item.Submarine, target);
|
||||
}
|
||||
if (!item.Submarine.DockedTo.Contains(target.item.Submarine))
|
||||
{
|
||||
item.Submarine.ConnectedDockingPorts.Add(target.item.Submarine, this);
|
||||
}
|
||||
|
||||
DockingTarget = target;
|
||||
DockingTarget.DockingTarget = this;
|
||||
@@ -869,11 +875,17 @@ namespace Barotrauma.Items.Components
|
||||
if (myWayPoint != null && targetWayPoint != null)
|
||||
{
|
||||
myWayPoint.FindHull();
|
||||
myWayPoint.linkedTo.Remove(targetWayPoint);
|
||||
myWayPoint.OnLinksChanged?.Invoke(myWayPoint);
|
||||
if (myWayPoint.linkedTo.Contains(targetWayPoint))
|
||||
{
|
||||
myWayPoint.linkedTo.Remove(targetWayPoint);
|
||||
myWayPoint.OnLinksChanged?.Invoke(myWayPoint);
|
||||
}
|
||||
targetWayPoint.FindHull();
|
||||
targetWayPoint.linkedTo.Remove(myWayPoint);
|
||||
targetWayPoint.OnLinksChanged?.Invoke(targetWayPoint);
|
||||
if (targetWayPoint.linkedTo.Contains(myWayPoint))
|
||||
{
|
||||
targetWayPoint.linkedTo.Remove(myWayPoint);
|
||||
targetWayPoint.OnLinksChanged?.Invoke(targetWayPoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private float userDeconstructorSpeedMultiplier = 1.0f;
|
||||
|
||||
private const float TinkeringSpeedIncrease = 1.5f;
|
||||
private const float TinkeringSpeedIncrease = 2.5f;
|
||||
|
||||
private ItemContainer inputContainer, outputContainer;
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace Barotrauma.Items.Components
|
||||
[Serialize(1.0f, true)]
|
||||
public float SkillRequirementMultiplier { get; set; }
|
||||
|
||||
private const float TinkeringSpeedIncrease = 1.5f;
|
||||
private const float TinkeringSpeedIncrease = 2.5f;
|
||||
|
||||
private enum FabricatorState
|
||||
{
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace Barotrauma.Items.Components
|
||||
public bool HasPower => IsActive && Voltage >= MinVoltage;
|
||||
public bool IsAutoControlled => pumpSpeedLockTimer > 0.0f || isActiveLockTimer > 0.0f;
|
||||
|
||||
private const float TinkeringSpeedIncrease = 1.5f;
|
||||
private const float TinkeringSpeedIncrease = 4.0f;
|
||||
|
||||
public Pump(Item item, XElement element)
|
||||
: base(item, element)
|
||||
|
||||
@@ -16,8 +16,6 @@ namespace Barotrauma.Items.Components
|
||||
private float deteriorationTimer;
|
||||
private float deteriorateAlwaysResetTimer;
|
||||
|
||||
private float repairBoost;
|
||||
|
||||
bool wasBroken;
|
||||
bool wasGoodCondition;
|
||||
|
||||
@@ -208,7 +206,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public float RepairDegreeOfSuccess(Character character, List<Skill> skills)
|
||||
{
|
||||
if (skills.Count == 0) return 1.0f;
|
||||
if (skills.Count == 0) { return 1.0f; }
|
||||
|
||||
float skillSum = (from t in skills let characterLevel = character.GetSkillLevel(t.Identifier) select (characterLevel - (t.Level * SkillRequirementMultiplier))).Sum();
|
||||
float average = skillSum / skills.Count;
|
||||
@@ -220,11 +218,14 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (qteSuccess)
|
||||
{
|
||||
repairBoost = RepairDegreeOfSuccess(CurrentFixer, requiredSkills) * 3 * (currentFixerAction == FixActions.Repair ? 1.0f : -1.0f);
|
||||
item.Condition += RepairDegreeOfSuccess(CurrentFixer, requiredSkills) * 3 * (currentFixerAction == FixActions.Repair ? 1.0f : -1.0f);
|
||||
}
|
||||
else
|
||||
else if (Rand.Range(0.0f, 2.0f) > RepairDegreeOfSuccess(CurrentFixer, requiredSkills))
|
||||
{
|
||||
repairBoost = (1 - RepairDegreeOfSuccess(CurrentFixer, requiredSkills)) * 10 * (currentFixerAction == FixActions.Repair ? -1.0f : 1.0f);
|
||||
ApplyStatusEffects(ActionType.OnFailure, 1.0f, CurrentFixer);
|
||||
#if SERVER
|
||||
GameMain.Server?.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ApplyStatusEffect, ActionType.OnFailure, this, CurrentFixer.ID });
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,6 +313,8 @@ namespace Barotrauma.Items.Components
|
||||
currentRepairItem = null;
|
||||
currentFixerAction = FixActions.None;
|
||||
#if CLIENT
|
||||
qteTimer = QteDuration;
|
||||
qteCooldown = 0.0f;
|
||||
repairSoundChannel?.FadeOutAndDispose();
|
||||
repairSoundChannel = null;
|
||||
#endif
|
||||
@@ -423,12 +426,6 @@ namespace Barotrauma.Items.Components
|
||||
wasGoodCondition = true;
|
||||
}
|
||||
|
||||
if (!MathUtils.NearlyEqual(repairBoost, 0.0f))
|
||||
{
|
||||
item.Condition += repairBoost;
|
||||
repairBoost = 0.0f;
|
||||
}
|
||||
|
||||
float fixDuration = MathHelper.Lerp(FixDurationLowSkill, FixDurationHighSkill, successFactor);
|
||||
fixDuration /= 1 + CurrentFixer.GetStatValue(StatTypes.RepairSpeed) + currentRepairItem?.Prefab.AddedRepairSpeedMultiplier ?? 0f;
|
||||
fixDuration /= 1 + item.GetQualityModifier(Quality.StatType.RepairSpeed);
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace Barotrauma.Items.Components
|
||||
//item in water -> we definitely want to send the True output
|
||||
isInWater = true;
|
||||
}
|
||||
else if (item.CurrentHull != null && item.CurrentHull.WaterPercentage > 0.0f)
|
||||
else if (item.CurrentHull != null && item.CurrentHull.WaterPercentage > 0.0f && item.CurrentHull.WaterVolume > 1.0f)
|
||||
{
|
||||
//(center of the) item in not water -> check if the water surface is below the bottom of the item's rect
|
||||
if (item.CurrentHull.Surface > item.Rect.Y - item.Rect.Height)
|
||||
@@ -102,7 +102,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
int waterPercentage = 0;
|
||||
//ignore minuscule amounts of water
|
||||
if (item.CurrentHull.WaterVolume < 1.0f)
|
||||
if (item.CurrentHull.WaterVolume > 1.0f)
|
||||
{
|
||||
waterPercentage = MathHelper.Clamp((int)Math.Ceiling(item.CurrentHull.WaterPercentage), 0, 100);
|
||||
}
|
||||
|
||||
@@ -2573,7 +2573,9 @@ namespace Barotrauma
|
||||
|
||||
private void WritePropertyChange(IWriteMessage msg, object[] extraData, bool inGameEditableOnly)
|
||||
{
|
||||
var allProperties = inGameEditableOnly ? GetInGameEditableProperties() : GetProperties<Editable>();
|
||||
//ignoreConditions: true = include all ConditionallyEditable properties at this point,
|
||||
//to ensure client/server doesn't get any properties mixed up if there's some conditions that can vary between the server and the clients
|
||||
var allProperties = inGameEditableOnly ? GetInGameEditableProperties(ignoreConditions: true) : GetProperties<Editable>();
|
||||
SerializableProperty property = extraData[1] as SerializableProperty;
|
||||
if (property != null)
|
||||
{
|
||||
@@ -2660,16 +2662,25 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private List<Pair<object, SerializableProperty>> GetInGameEditableProperties()
|
||||
private List<Pair<object, SerializableProperty>> GetInGameEditableProperties(bool ignoreConditions = false)
|
||||
{
|
||||
return GetProperties<ConditionallyEditable>()
|
||||
.Where(ce => ce.Second.GetAttribute<ConditionallyEditable>().IsEditable(this))
|
||||
.Union(GetProperties<InGameEditable>()).ToList();
|
||||
if (ignoreConditions)
|
||||
{
|
||||
return GetProperties<ConditionallyEditable>().Union(GetProperties<InGameEditable>()).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetProperties<ConditionallyEditable>()
|
||||
.Where(ce => ce.Second.GetAttribute<ConditionallyEditable>().IsEditable(this))
|
||||
.Union(GetProperties<InGameEditable>()).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadPropertyChange(IReadMessage msg, bool inGameEditableOnly, Client sender = null)
|
||||
{
|
||||
var allProperties = inGameEditableOnly ? GetInGameEditableProperties() : GetProperties<Editable>();
|
||||
//ignoreConditions: true = include all ConditionallyEditable properties at this point,
|
||||
//to ensure client/server doesn't get any properties mixed up if there's some conditions that can vary between the server and the clients
|
||||
var allProperties = inGameEditableOnly ? GetInGameEditableProperties(ignoreConditions: true) : GetProperties<Editable>();
|
||||
if (allProperties.Count == 0) { return; }
|
||||
|
||||
int propertyIndex = 0;
|
||||
@@ -2686,9 +2697,12 @@ namespace Barotrauma
|
||||
if (!ic.AllowInGameEditing) { allowEditing = false; }
|
||||
}
|
||||
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer && !CanClientAccess(sender))
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
|
||||
{
|
||||
allowEditing = false;
|
||||
if (!CanClientAccess(sender) || !(property.GetAttribute<ConditionallyEditable>()?.IsEditable(this) ?? true))
|
||||
{
|
||||
allowEditing = false;
|
||||
}
|
||||
}
|
||||
|
||||
Type type = property.PropertyType;
|
||||
|
||||
@@ -861,13 +861,13 @@ namespace Barotrauma
|
||||
System.Diagnostics.Debug.Assert(this != wayPoint2);
|
||||
if (!linkedTo.Contains(wayPoint2))
|
||||
{
|
||||
linkedTo.Add(wayPoint2);
|
||||
OnLinksChanged?.Invoke(this);
|
||||
linkedTo.Add(wayPoint2);
|
||||
}
|
||||
if (!wayPoint2.linkedTo.Contains(this))
|
||||
{
|
||||
wayPoint2.linkedTo.Add(this);
|
||||
wayPoint2.OnLinksChanged?.Invoke(wayPoint2);
|
||||
wayPoint2.linkedTo.Add(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1105,7 +1105,6 @@ namespace Barotrauma
|
||||
Ladders = null;
|
||||
OnLinksChanged = null;
|
||||
WayPointList.Remove(this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Barotrauma.Networking
|
||||
static class NetIdUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// Is newID more recent than oldID
|
||||
/// Is newID more recent than oldID, i.e. newId > oldId accounting for ushort rollover
|
||||
/// </summary>
|
||||
public static bool IdMoreRecent(ushort newID, ushort oldID)
|
||||
{
|
||||
@@ -22,6 +22,12 @@ namespace Barotrauma.Networking
|
||||
(id2 > id1) && (id2 - id1 > ushort.MaxValue / 2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// newId >= oldId accounting for ushort rollover (newer or equals)
|
||||
/// </summary>
|
||||
public static bool IdMoreRecentOrMatches(ushort newId, ushort oldId)
|
||||
=> !IdMoreRecent(oldId, newId);
|
||||
|
||||
public static ushort Difference(ushort id1, ushort id2)
|
||||
{
|
||||
int diff = id2 > id1 ? id2 - id1 : id1 - id2;
|
||||
|
||||
@@ -1067,6 +1067,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
#if SERVER
|
||||
MultiPlayerCampaign.UpdateCampaignSubs();
|
||||
SelectNonHiddenSubmarine();
|
||||
#endif
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,182 +1,25 @@
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
v0.15.17.0
|
||||
v0.15.21.0
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
|
||||
- Fixed "allow linking wifi to chat" server setting preventing clients without the permission to manage server settings from using their headsets.
|
||||
- Fixed repair minigame not working correclty if the user has a talent that allows repairing past max condition.
|
||||
- Fixed "error in Order Pump Water - the number of option names doesn't match the number of options" errors in Russian, Korean and Traditional Chinese.
|
||||
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
v0.15.20.0
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
|
||||
Changes:
|
||||
- New submarine: Orca 2.
|
||||
- Improved monster spawning: different monsters spawn in different biomes and tougher monsters are introduced gradually during the course of the campaign. WIP, probably requires balancing and adjusting. Feedback is welcome.
|
||||
- Adjusted gardening: the plants now require less continuous attention, making gardening a more viable "downtime activity" that you can focus on when there's nothing else to do, and ignore when you're busy without killing the plants.
|
||||
- Readded GameAnalytics, a library that allows us to collect gameplay statistics and error reports automatically. Sending statistics is completely optional: when you launch the game, you're asked whether you want to allow the game to send us data or not. If you decline, no data of any kind is collected. The collected data is completely anonymous and doesn't contain any personal information, but only things such as error reports and statistics about the selected game mode, submarine, missions and mods.
|
||||
- Added a simple QTE "minigame" to the repair interface. Allows speeding up the repairs slightly and hopefully makes repairing feel a little more engaging.
|
||||
- Characters can climb up ladders faster by holding the sprint key.
|
||||
- Mudraptor shell shields block projectiles and can be destroyed by firing at them.
|
||||
- Bots take previous heals into account when determining when to react to attacks. Fixes deusizine and liquid oxygenite aggroing the bots when using them to treat oxygen loss.
|
||||
- Changed the way purchasable submarines for the multiplayer campaign are selected: instead of choosing them when creating the campaign, all of the server's visible submarines are made available for purchase.
|
||||
- Diving suits play a different warning sound when low on oxygen (<5% left in tank).
|
||||
- PUCS doesn't consume oxygen tanks in rooms with oxygen.
|
||||
- Added new option-specific bot dialogue for when bots can't find "loadables" for the Load Items order (unstable only).
|
||||
- Reworked "evasive maneuvers": now gives 15% more money for nest/swarm missions instead of giving attack bonus inside submarine.
|
||||
- Rework "expanded research": whenever you or another allied crewmember deconstructs depleted fuel, they gain 400 experience. This effect can only occur up to 3 times until you finish another mission.
|
||||
- Prototype Steam Cannon can damage ballast flora.
|
||||
- Water detectors treat minuscule amounts (< 1.0 water volume) as 0.
|
||||
- Improvements to the "infiltration" outpost event: you can talk to any of the clowns to progress, not just the one that spawned 1st, and the clowns head to the airlock when told to leave.
|
||||
- Improved the bots door interaction so that they don't slam the door at your face, nor bump into closed doors so often, or keep "smashing the select key" as frequently. There's now a three second cooldown after succesfully pressing a button before next attempt.
|
||||
- Changes to the default order assignment priorities, which determine the initial order of the orders when multiple is issued. You can still alter the order manually by dragging the order icons.
|
||||
- Bots now treat handcuffed targets as neutralized, unless they are hostiles spawned from events. Fixes e.g. bots killing captured prisoners, but also allows you to submit to the outpost guards by handcuffing yourself.
|
||||
- Load Items order: bots now prioritize containers that have empty space.
|
||||
- Load Items order: the Refill Oxygen Tanks option now also puts tanks into oxygen tank shelves.
|
||||
- Load Items order: bots now prioritize items further from the target condition when searching for items to laod, i.e. emptier oxygen tanks and battery cells and fuller ammunition boxes.
|
||||
|
||||
Fixes:
|
||||
- Fixed certain monsters (e.g. hammerheads) attacking each other (unstable only).
|
||||
- Fixed mudraptors and crawlers trying to swim to the bottom of the ocean.
|
||||
- Fixed other clients' characters sometimes disappearing in MP when moving from sub to another (unstable only).
|
||||
- Fixes and improvements to Orca 2.
|
||||
- Fixed canister shell texture path (unstable only).
|
||||
- Fixed structures without a collider not being taken into account when determining which submarines are visible, causing them to vanish if there are only structures without a collider on the screen.
|
||||
- Fixed Round and Ceil components returning -0 when rounding a negative value to 0.
|
||||
- Fixed inability to swim up through a small hull on top of another one (e.g. the upper airlock in R-29).
|
||||
- Fixed skillbooks, oxygenite shards and sulphurite shards not spawning in crates.
|
||||
- Fixed name of the currently installed turret not being displayed in the submarine upgrade menu.
|
||||
- Fixed AI gunners not shooting at visible enemies inside the enemy submarine.
|
||||
- Prevent bots from healing the targets that have recently attacked them. Fixes bots healing and shooting you at the same time.
|
||||
- Fixed rescue order (healing) not working outside of the sub.
|
||||
- Fixed bots not knowing how to use the Rapid Fissile Accelerator. Also improves on how they use smg, assault rifle, and autoshotgun.
|
||||
- Fixed status monitor's electrical view not showing the power/load values in Korean.
|
||||
- Fixed status monitor displaying water levels strangely in multi-hull rooms (unstable only).
|
||||
- Fixed water flow sound volume having no upper limit, sometimes causing the sounds to drown out everything else (unstable only).
|
||||
- Fixed bots trying to equip a scooter when their hands are occupied by something that can't be put in the inventory (e.g. a crate), leading to weird twitching when they drop and immediately pick up the carried item.
|
||||
- Fixed unconscious NPCs being able to see you steal.
|
||||
- Fixed inability to order bots to operate turrets that are controlled via wifi components (unstable only).
|
||||
- Fixed bots staying in the "fight intruders" state indefinitely when there are neutralized (= handcuffed) hostiles on board, and repeatedly reporting that there are hostiles on board.
|
||||
- Bots stop moving before starting to repair a device. Fixes bots "flying" when the repair fails, because they'd start the repair while still running at full speed and would keep the momentum if they get stunned because of the failed repair.
|
||||
- Fixed bots sometimes repathing too eagerly while they are on ladders, sometimes causing them to get stuck in places where they should switch from a ladder to another one nearby.
|
||||
- Fixed looking at the sonar sometimes causing a significant performance hit (most often in the abyss). If a path to a marker couldn't be found when determining the distance to the marker, the game would keep trying to find a path every frame.
|
||||
- Fixed "expert commando" talent affecting turrets.
|
||||
- Fixed Alien_Entrance3's left opening getting connected to other modules instead of being used as an entrance.
|
||||
- Fixed coilgun draining ammo boxes at the same rate regardless of the number of linked loaders.
|
||||
- Fixed some of the artifacts still playing sounds when inside a transport case.
|
||||
- Fixed inability to put genetic materials into a container inside another container.
|
||||
- Fixed characters legs sometimes bending the wrong way around when climbing (seems to happen most often when trying to get on ladders while swimming up-side down).
|
||||
- Fixed borked "Front E P2" collider.
|
||||
- Fixed bots taking items from fabricators/deconstructors when ordered to load items.
|
||||
- Fixed bots sometimes running headlessly for a brief period after having been ordered to load items.
|
||||
- Fixed hostages in the abandoned outpost rescue mission refusing to follow a player that has some diving gear on they don't have access to.
|
||||
- Fixed pirates giving redundant orders and consequently talking too much in the chat.
|
||||
- Fixed pirates not always shooting monsters if there's few of them.
|
||||
- Fixes to the bot navigation outside of the sub.
|
||||
- Fixed bots still trying to go through destructible ice chunks.
|
||||
- Fixed bots not closing the airlock doors when they go outside
|
||||
- Fixed bots not always trying to press the right button to interact with a door.
|
||||
- Fixed bots getting stuck when trying to follow a target with some diving gear they don't have access to. Now they should self-dismiss the order instead.
|
||||
- Fixed auto-dismissing orders clearing all the orders instead of just the one that should dismiss.
|
||||
- Fixed the follow distances between the characters when there's multiple bots following the player.
|
||||
- Fixed monsters always ignoring all items inside the sub when they are outside, consequently they didn't target the sonar or the engine, for example.
|
||||
- Fixed bots sometimes deploying Kastrull's drone for no reason.
|
||||
- Fixed the Load Items order sometimes dropping one item from the target container, even when there's space for the new item.
|
||||
- Fixed bots removing items too aggressively from their preferred containers (e.g. oxygen tanks from diving suits) during the Load Items order when the items had been even just very slightly used.
|
||||
|
||||
Modding:
|
||||
- Fixed overriding a Controller component (e.g. button) resetting its Toggle and State settings.
|
||||
- Fixed ParticleEmitter's angle not getting mirrored when spawned by a mirrored item.
|
||||
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
v0.15.16.0
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
|
||||
Changes:
|
||||
- Added a simple QTE "minigame" to the repair interface. Allows speeding up the repairs slightly and hopefully makes repairing feel a little more engaging.
|
||||
- Medical curtains can be opened and closed.
|
||||
- Restrict the amount of additional cargo you can choose in multiplayer: max 10 items of a type, max 20 types of items.
|
||||
- Connected power to oxygen tank shelves in Azimuth, Berilia, Dugong, R-29 and Remora.
|
||||
- Allow editing item quality in the sub editor.
|
||||
- Changed the way purchasable submarines for the multiplayer campaign are selected: instead of choosing them when creating the campaign, all of the server's visible submarines are made available for purchase.
|
||||
- Added a new "Load Items" order with options "Recharge battery cells", "Refill oxygen tanks", and "Reload ammo": bots will take battery cells to be recharged, take oxygen tanks to be refilled, or place more ammo to loaders depending on the order option.
|
||||
- Reduced initial assignment priority for Operate orders: Operate Reactor, Operate Weapons, and Steer orders will now be assigned as the lowest priority order by default, but the current order priorities can still be adjusted like before by rearranging the orders on the crew list.
|
||||
- Minor adjustments to the the monster spawns in the ruins.
|
||||
- Husks now remain neutral towards characters that are late in the husk transformation, unless they act offensively.
|
||||
- Reduce Husk and Humanhusk sight from 1 to 0.5.
|
||||
- Prepare for expedition order: the bots now try to take five oxygen tanks instead of just one.
|
||||
- Prepare for experition order: require a diving suit for the order to complete.
|
||||
- Oxygenite shards are no longer oxygen sources and can't be inserted into diving gear or tools directly. They are still a source of liquid oxygenite, which can be used to craft oxygenite tanks.
|
||||
- Allow to grab targets when their inventory can be accessed. Allow to access the inventory of the bots.
|
||||
- Adjust the health interface: target is shown closer to the center of the screen.
|
||||
- Shotguns now spawn with 6 shells, autoshotguns with 8 (a full stack).
|
||||
- Add some dialog for the bots when they are getting attacked outside a friendly sub to tell the player why they are fleeing from an enemy and that they don't have a weapon.
|
||||
|
||||
Talent improvements and fixes:
|
||||
- Overall balancing to the stats boots from talents.
|
||||
- Fixed "tandem fire" crashing the game if there are no other crewmates present.
|
||||
- Fixed "safety first" talent giving you mechanical skill when you gain electrical skill instead of the other way around.
|
||||
- Fixed talent menu showing extra talents as still being selectable after picking all-seeing-eye, even if there's no talent points left (unstable only).
|
||||
- Reworked "implacable": now allows the character to stay conscious for 15 seconds after falling below 0 health.
|
||||
- Reworked "field medic": if you complete a mission and all crew members survived, you gain medical skill.
|
||||
- Reworked "beat cop": now gives 25% repair speed and increases inflicted stuns by 25% (and the tackle).
|
||||
- Reworked "reverse engineer": whenever you deconstruct an alien artifact, you have a 50% chance to gain double output from it and gain 8 to a random skill. Small alien artifacts, when deconstructed, give 4 skill instead.
|
||||
- Reworked "curiosity": whenever you deconstruct an alien artifact, you and another random allied crewmember gains 125 experience. Small alien artifacts, when deconstructed, give 50 experience instead.
|
||||
- Reworked "expert commando": now gives, to ranged weapons, 70% spread reduction, 40% attack multiplier and 30% attack speed reduction while crouched.
|
||||
- Reworked "gene therapist": now gives an additional 25% medical item potency, correctly displays as adding a flat 10% to each refined genetic material.
|
||||
- Reworked "genetic stability": no longer gives 25% repair speed, and instead gives 15 to all skills. Probability of tainting genetic material reduced to 50%.
|
||||
- Reworked "still kicking": now rapidly heals over a short duration instead.
|
||||
- Reworked "stand and deliver": assistant skillbook can no longer be used on another character, instead the nearest ally gains 5 to all skills when the book is read by the talent owner.
|
||||
- Reworked "first aid training": Now gives a flat 35% increase to medical item potency when applied to the character.
|
||||
- "Advanced splicing", "optimized power-flow" and "elbow grease" can now only give up to 100 skill bonus.
|
||||
- Adjustments to some of the ability descriptions to address some inaccuracies/ambiguities.
|
||||
- Rebalanced combat stimulant: now applies faster, but less in total per dose. Healing reduced.
|
||||
- Droped type "poison" from chem addiction, making it non-healable (only chem withdrawal can be healed).
|
||||
|
||||
Fixes:
|
||||
- Fixed certain wires in vanilla subs being impossible to remove.
|
||||
- Improvements to cave waypoints: should fix bots getting stuck next to destructible ice chunks even if there's a way past them.
|
||||
- Fixed other clients' characters sometimes appearing to teleport outside the sub for 1 frame when moving from sub to another, leading to further issues if the client has water-sensitive items in their inventory.
|
||||
- Fixed gaps sometimes getting connected to incorrect hulls between docking ports, preventing water from flowing down from the space between the ports.
|
||||
- Fixed mudraptor shell armor's sprite depth getting messed up when climbing ladders.
|
||||
- Fixed drunkenness, opiate withdrawal and chem withdrawal not causing nausea.
|
||||
- Fixed wire nodes getting misplaced in the sub editor when loading mirrored wires.
|
||||
- Fixed whitelist controls getting disabled when adding new players to the list if whitelist wasn't enabled when opening the server settings.
|
||||
- Fixed hardened/dementonite crowbars not opening doors faster than normal ones.
|
||||
- Fixed campaign setup menu going crazy if you try to scroll it with arrow keys.
|
||||
- Fixed bots losing their items if you quit the 1st MP campaign round without saving, continue, and repeat that again.
|
||||
- Fixed cargo sometimes spawning inside the floor. Happened because the spawn position was determined based on the purchased item's size, instead of the crate the item spawns in.
|
||||
- Fixed playstyle always being displayed as Serious in the server lobby unless you're hosting yourself.
|
||||
- Fixed handheld status monitor drawing the water levels and character icons of the previous sub when it's taken outside.
|
||||
- Fixed spawnitem command not working in the sub editor.
|
||||
- Fixed "slipsuit.png not found" error" when placing a slipsuit in a locker (unstable only).
|
||||
- Fixed alien pistol not having a crosshair.
|
||||
- Fixed weapon skill above 100 making weapons less accurate.
|
||||
- Fixed misaligned outpost reactor meters.
|
||||
- Fixed R and T not bringing up the chat if it's minimized (unstable only).
|
||||
- Fixed terminal inputs not working (unstable only).
|
||||
- Fixed hulls' "hidden in game" setting doing nothing.
|
||||
- Fixed certain items causing the "analyzeitem" and "deconstructvalue" console commands to crash.
|
||||
- Fixed context menus not opening when right-clicking player names in the chat and server log.
|
||||
- Improved the error message shown when a Steam lobby could not be created.
|
||||
- Reduced the severity and frequency of the "Maximum packet size exceeded" error in the server lobby.
|
||||
- Fixed the contextual order for fiding a weapon not targeting the selected item.
|
||||
- Fixed combat objective overriding the priority of find safety objective when the combat objective shouldn't even be active, leading to bots sometimes suffocating after combat if they don't have enough oxygen in the currently equipped tank.
|
||||
- Fixed bots trying to shoot through level walls.
|
||||
- Prepare for expedition: Fix bots not equipping a diving suit in multiplayer game.
|
||||
- Fixed sprite bleed in the outpost computer terminal sprite.
|
||||
- Fixed campaign getting "locked" if the submarine undocks immediately at the start of the round (on the first frame, e.g. as a result of some custom docking circuit).
|
||||
- Fixed deconstructor being unable to combine the output items if they're inside a container in the output slots.
|
||||
|
||||
Modding:
|
||||
- Fixed certain explosion flashduration values causing the light to flicker/loop.
|
||||
- Fixed remaining errors with talent overrides.
|
||||
- Allow the enemy ai to target using groups in addition to species names.
|
||||
- Move the turret ammo box definitions from containers.xml to where the gun and the ammo is defined.
|
||||
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
v0.15.15.0
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
|
||||
- Fixed crashing when bots switch to the combat state.
|
||||
- Removed stun tools from riot officer loadout, replaced with riot shotgun.
|
||||
- Burns slowly heal by themselves, adjusted radiation poisoning accordingly.
|
||||
- Fixed bots being unable to clean up items stolen from an outpost after leaving the outpost.
|
||||
- Fixed incorrect base skill being used in skill reduction calculation.
|
||||
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
v0.15.14.0
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
|
||||
Changes:
|
||||
- Adjusted gardening: the plants now require less continuous attention, making gardening a more viable "downtime activity" that you can focus on when there's nothing else to do, and ignore when you're busy without killing the plants.
|
||||
- Added "Pump In" option to the contextual "Pump Water" order.
|
||||
- Added "fuel_percentage_left" output to reactors. Outputs the sum of the fuel rods' condition percentage, as opposed to the total "heating power" of the rods like the "fuel_out" output.
|
||||
- Powered down reactors don't zap the user when repairing.
|
||||
@@ -199,6 +42,19 @@ Changes:
|
||||
- Added a menu to hide submarines in the server lobby, allowing hosts to remove vanilla submarines from the list without replacing the content package.
|
||||
- Added LOS effect to the server settings.
|
||||
- Added line break support to the server message.
|
||||
- Connected the diving suit lockers on the vanilla submarines to the power grid so that they refill the contained oxygen tanks.
|
||||
- Connected the oxygen shelves on Humpback to the power grid.
|
||||
- Allowed in-game editing of lamps in R-29.
|
||||
- Mudraptor shell shields block projectiles and can be destroyed by firing at them.
|
||||
- Prototype Steam Cannon can damage ballast flora.
|
||||
- Water detectors treat minuscule amounts (< 1.0 water volume) as 0.
|
||||
- Improvements to the "infiltration" outpost event: you can talk to any of the clowns to progress, not just the one that spawned 1st, and the clowns head to the airlock when told to leave.
|
||||
- Medical curtains can be opened and closed.
|
||||
- Restricted the amount of additional cargo you can choose in multiplayer: max 10 items of a type, max 20 types of items.
|
||||
- Allow editing item quality in the sub editor.
|
||||
- Removed stun tools from riot officer loadout, replaced with riot shotgun.
|
||||
- Burns slowly heal by themselves, adjusted radiation poisoning accordingly.
|
||||
- Shotguns now spawn with 6 shells, autoshotguns with 8 (a full stack).
|
||||
|
||||
Multiplayer fixes:
|
||||
- Fixed campaign character resetting if the client, disconnects, rejoins and respawns on the same round after their character has gotten killed.
|
||||
@@ -211,30 +67,83 @@ Multiplayer fixes:
|
||||
- Fixed crashing if you start the round as a spectator, take control of someone with console commands and try to access the tab menu's character tab.
|
||||
- Fixed empty exploding coilgun ammo boxes exploding client-side when deconstructed.
|
||||
- Fixed disabling friendly fire preventing buffs from being applied to crewmates, while allowing harmful afflictions to be applied (= the setting basically worked the wrong way around).
|
||||
- Fixed other clients' characters sometimes appearing to teleport outside the sub for 1 frame when moving from sub to another, leading to further issues if the client has water-sensitive items in their inventory.
|
||||
- Fixed whitelist controls getting disabled when adding new players to the list if whitelist wasn't enabled when opening the server settings.
|
||||
- Fixed bots losing their items if you quit the 1st MP campaign round without saving, continue, and repeat that again.
|
||||
- Fixed playstyle always being displayed as Serious in the server lobby unless you're hosting yourself.
|
||||
- Reduced the severity and frequency of the "Maximum packet size exceeded" error in the server lobby.
|
||||
- Fixed context menus not opening when right-clicking player names in the chat and server log.
|
||||
- Improved the error message shown when a Steam lobby could not be created.
|
||||
|
||||
Talent fixes:
|
||||
- Fixed unlocking "all seeing eye" preventing you from unlocking further talents until you've gained enough EXP to compensate for the 3 "free" talents.
|
||||
Talent improvements and fixes:
|
||||
- Overall balancing to the stats boots from talents.
|
||||
- Adjustments to some of the ability descriptions to address some inaccuracies/ambiguities.
|
||||
- Reworked "implacable": now allows the character to stay conscious for 15 seconds after falling below 0 health.
|
||||
- Reworked "field medic": if you complete a mission and all crew members survived, you gain medical skill.
|
||||
- Reworked "beat cop": now gives 25% repair speed and increases inflicted stuns by 25% (and the tackle).
|
||||
- Reworked "reverse engineer": whenever you deconstruct an alien artifact, you have a 50% chance to gain double output from it and gain 8 to a random skill. Small alien artifacts, when deconstructed, give 4 skill instead.
|
||||
- Reworked "curiosity": whenever you deconstruct an alien artifact, you and another random allied crewmember gains 125 experience. Small alien artifacts, when deconstructed, give 50 experience instead.
|
||||
- Reworked "expert commando": now gives, to ranged weapons, 70% spread reduction, 40% attack multiplier and 30% attack speed reduction while crouched.
|
||||
- Reworked "gene therapist": now gives an additional 25% medical item potency, correctly displays as adding a flat 10% to each refined genetic material.
|
||||
- Reworked "genetic stability": no longer gives 25% repair speed, and instead gives 15 to all skills. Probability of tainting genetic material reduced to 50%.
|
||||
- Reworked "still kicking": now rapidly heals over a short duration instead.
|
||||
- Reworked "stand and deliver": assistant skillbook can no longer be used on another character, instead the nearest ally gains 5 to all skills when the book is read by the talent owner.
|
||||
- Reworked "first aid training": Now gives a flat 35% increase to medical item potency when applied to the character.
|
||||
- Reworked "evasive maneuvers": now gives 15% more money for nest/swarm missions instead of giving attack bonus inside submarine.
|
||||
- Reworked "expanded research": whenever you or another allied crewmember deconstructs depleted fuel, they gain 400 experience. This effect can only occur up to 3 times until you finish another mission.
|
||||
- "Scrap savant" and "scrounger" only spawn the scrap in items with the tag "container" and only if the container can hold scrap. Fixes ability to generate free scrap by placing containers like detonators and portable pumps in the wrecks.
|
||||
- "Advanced splicing", "optimized power-flow" and "elbow grease" can now only give up to 100 skill bonus.
|
||||
- Fixed "canned heat" not increasing the quality of fabricated oxygenite tanks.
|
||||
- Fixed "pyromaniac" applying the buff to the enemy you're damaging instead of your character.
|
||||
- Fixed server ending the round if the last player alive is an assistant with the "still kicking" talent and said assistant falls unconscious.
|
||||
- Electrochemist talent doesn't stun the attacker if the attack doesn't apply any harmful afflictions (e.g. if it only applies buffs or gives experience).
|
||||
- Fixed high-quality items with whose max condition is above 100% not being accepted as fabrication ingredients.
|
||||
- Fixed autofill not working on the new talent items.
|
||||
- Added PreferredContainers to the new talent items to allow the bots to clean them up.
|
||||
- Fixed "crew layabout" applying stat boosts to enemies as well.
|
||||
- Fixed "expert commando" talent affecting turrets.
|
||||
- Fixed hardened/dementonite crowbars not opening doors faster than normal ones.
|
||||
- Fixed unlocking "all seeing eye" preventing you from unlocking further talents until you've gained enough EXP to compensate for the 3 "free" talents.
|
||||
- Fixed high-quality items with whose max condition is above 100% not being accepted as fabrication ingredients.
|
||||
- Fixed "tandem fire" crashing the game if there are no other crewmates present.
|
||||
- Fixed "safety first" talent giving you mechanical skill when you gain electrical skill instead of the other way around.
|
||||
- Added PreferredContainers to the new talent items to allow the bots to clean them up.
|
||||
- Rebalanced combat stimulant: now applies faster, but less in total per dose. Healing reduced.
|
||||
- Dropped type "poison" from chem addiction, making it non-healable (only chem withdrawal can be healed).
|
||||
|
||||
AI:
|
||||
- New order: Find Weapon
|
||||
- New order: Prepare for Expedition
|
||||
- New order: Prepare for Expedition.
|
||||
- New order: "Load Items", with options "Recharge battery cells", "Refill oxygen tanks", and "Reload ammo". Bots will take battery cells to be recharged, take oxygen tanks to be refilled, or place more ammo to loaders depending on the order option.
|
||||
- Added an option to pump in water. Only applicable to pumps that are not automatically controlled.
|
||||
- Orders that cannot be completed should now be dismissed automatically instead of keeping active but doing nothing.
|
||||
- The bots should now tell you when they can't follow an order, instead of always replying positively.
|
||||
- Changes to the default order assignment priorities, which determine the initial order of the orders when multiple is issued. You can still alter the order manually by dragging the order icons.
|
||||
- Fixed bots getting stuck with invalid paths for too long.
|
||||
- Fixed AIObjectiveGetItem not working properly when we try to ignore the items that already are in the inventory. In practice, only affects the find better weapons behavior in the combat objective (Fight Intruders).
|
||||
- Bots don't automatically unequip PUCS when they don't need diving gear.
|
||||
- Don't allow bots to heal pets (because they are likely to just kill them).
|
||||
- Fixed bots trying to equip diving gear when they have spliced genes that give pressure immunity and/or remove the need for oxygen.
|
||||
- Improved the bots door interaction so that they don't slam the door at your face, nor bump into closed doors so often, or keep "smashing the select key" as frequently. There's now a three second cooldown after succesfully pressing a button before next attempt.
|
||||
- Bots now hold still while waiting a door to open instead of moving towards it.
|
||||
- Bots now only put oxygen tanks into oxygen generators with the "Refill Oxygen Tanks" order option.
|
||||
- Bots take previous heals into account when determining when to react to attacks. Fixes deusizine and liquid oxygenite aggroing the bots when using them to treat oxygen loss.
|
||||
- Bots now treat handcuffed targets as neutralized, unless they are hostiles spawned from events. Fixes e.g. bots killing captured prisoners, but also allows you to submit to the outpost guards by handcuffing yourself.
|
||||
- Prevent bots from healing the targets that have recently attacked them. Fixes bots healing and shooting you at the same time.
|
||||
- Fixed rescue order (healing) not working outside of the sub.
|
||||
- Fixed bots not knowing how to use the Rapid Fissile Accelerator. Also improves on how they use smg, assault rifle, and autoshotgun.
|
||||
- Fixed unconscious NPCs being able to see you steal.
|
||||
- Fixed bots sometimes repathing too eagerly while they are on ladders, sometimes causing them to get stuck in places where they should switch from a ladder to another one nearby.
|
||||
- Fixed hostages in the abandoned outpost rescue mission refusing to follow a player that has some diving gear on they don't have access to.
|
||||
- Fixed pirates giving redundant orders and consequently talking too much in the chat.
|
||||
- Fixed pirates not always shooting monsters if there's only a few of them.
|
||||
- Fixed bots not always trying to press the right button to interact with a door.
|
||||
- Fixed bots getting stuck when trying to follow a target with some diving gear they don't have access to. Now they should self-dismiss the order instead.
|
||||
- Fixed bots sometimes deploying Kastrull's drone for no reason.
|
||||
- Improvements to cave waypoints: should fix bots getting stuck next to destructible ice chunks even if there's a way past them.
|
||||
- Husks now remain neutral towards characters that are late in the husk transformation, unless they act offensively.
|
||||
- Reduced Husk and Humanhusk sight from 1 to 0.5.
|
||||
- Oxygenite shards are no longer oxygen sources and can't be inserted into diving gear or tools directly. They are still a source of liquid oxygenite, which can be used to craft oxygenite tanks.
|
||||
- Added some dialog for the bots when they are getting attacked outside a friendly sub to tell the player why they are fleeing from an enemy and that they don't have a weapon.
|
||||
- Fixed combat objective overriding the priority of find safety objective when the combat objective shouldn't even be active, leading to bots sometimes suffocating after combat if they don't have enough oxygen in the currently equipped tank.
|
||||
|
||||
Misc fixes:
|
||||
- Exploding the abandoned outpost reactor doesn't damage the player sub in missions that require destroying it.
|
||||
@@ -287,6 +196,42 @@ Misc fixes:
|
||||
- Restrict downwards movement when a character has reached the bottom of a ladder to fix phasing through the floor.
|
||||
- Fixed characters' feet dangling in the air when moving from a ladder to another (e.g. when climbing from the sub to the outpost).
|
||||
- Adjusted flamethrower and prototype steam cannon particles to get them to match the range of the weapons more closely.
|
||||
- Fixed most outpost modules being named as airlock and consequently defined as "wet rooms". Fixes bots still slamming doors and hatches on each others face while moving around in the outposts.
|
||||
- Fixed portable pump consuming batteries when it's not pumping in/out.
|
||||
- Fixed waypoint connections on Remora drone causing navigation issues for the bots.
|
||||
- Fixed undocking a drone (e.g. on Remora/Kastrull) permanently breaking the navigation between the shuttle and the main sub.
|
||||
- Fixed mudraptors and crawlers trying to swim to the bottom of the ocean.
|
||||
- Fixed structures without a collider not being taken into account when determining which submarines are visible, causing them to vanish if there are only structures without a collider on the screen.
|
||||
- Fixed Round and Ceil components returning -0 when rounding a negative value to 0.
|
||||
- Fixed inability to swim up through a small hull on top of another one (e.g. the upper airlock in R-29).
|
||||
- Fixed skillbooks, oxygenite shards and sulphurite shards not spawning in crates.
|
||||
- Fixed name of the currently installed turret not being displayed in the submarine upgrade menu.
|
||||
- Fixed AI gunners not shooting at visible enemies inside the enemy submarine.
|
||||
- Fixed status monitor's electrical view not showing the power/load values in Korean.
|
||||
- Fixed bots trying to equip a scooter when their hands are occupied by something that can't be put in the inventory (e.g. a crate), leading to weird twitching when they drop and immediately pick up the carried item.
|
||||
- Bots stop moving before starting to repair a device. Fixes bots "flying away" when the repair fails, because they'd start the repair while still running at full speed and would keep the momentum if they get stunned because of the failed repair.
|
||||
- Fixed looking at the sonar sometimes causing a significant performance hit (most often in the abyss). If a path to a marker couldn't be found when determining the distance to the marker, the game would keep trying to find a path every frame.
|
||||
- Fixed Alien_Entrance3's left opening getting connected to other modules instead of being used as an entrance.
|
||||
- Fixed coilgun draining ammo boxes at the same rate regardless of the number of linked loaders.
|
||||
- Fixed some of the artifacts still playing sounds when inside a transport case.
|
||||
- Fixed inability to put genetic materials into a container inside another container.
|
||||
- Fixed characters' legs sometimes bending the wrong way around when climbing (seems to happen most often when trying to get on ladders while swimming up-side down).
|
||||
- Fixed borked "Front E P2" collider.
|
||||
- Fixed certain wires in vanilla subs being impossible to remove.
|
||||
- Fixed gaps sometimes getting connected to incorrect hulls between docking ports, preventing water from flowing down from the space between the ports.
|
||||
- Fixed mudraptor shell armor's sprite depth getting messed up when climbing ladders.
|
||||
- Fixed drunkenness, opiate withdrawal and chem withdrawal not causing nausea.
|
||||
- Fixed wire nodes getting misplaced in the sub editor when loading mirrored wires.
|
||||
- Fixed campaign setup menu going crazy if you try to scroll it with arrow keys.
|
||||
- Fixed handheld status monitor drawing the water levels and character icons of the previous sub when it's taken outside.
|
||||
- Fixed spawnitem command not working in the sub editor.
|
||||
- Fixed alien pistol not having a crosshair.
|
||||
- Fixed weapon skill above 100 making weapons less accurate.
|
||||
- Fixed cargo sometimes spawning inside the floor. Happened because the spawn position was determined based on the purchased item's size, instead of the crate the item spawns in.
|
||||
- Fixed campaign getting "locked" if the submarine undocks immediately at the start of the round (on the first frame, e.g. as a result of some custom docking circuit).
|
||||
- Fixed deconstructor being unable to combine the output items if they're inside a container in the output slots.
|
||||
- Fixed misaligned outpost reactor meters.
|
||||
- Fixed sprite bleed in the outpost computer terminal sprite.
|
||||
|
||||
Modding:
|
||||
- Fixed inability to override talent trees.
|
||||
@@ -299,6 +244,13 @@ Modding:
|
||||
- Fixed crashing when trying to create a non-humanoid that can walk in the character editor.
|
||||
- Added a randomize button for level editor seed.
|
||||
- Fixed fabricators without a repairable component crashing the game when activated.
|
||||
- Fixed overriding a Controller component (e.g. button) resetting its Toggle and State settings.
|
||||
- Fixed ParticleEmitter's angle not getting mirrored when spawned by a mirrored item.
|
||||
- Fixed certain explosion flashduration values causing the light to flicker/loop.
|
||||
- Allow the enemy AI to target using groups in addition to species names.
|
||||
- Moved the turret ammo box definitions from containers.xml to where the gun and the ammo are defined.
|
||||
- Fixed hulls' "hidden in game" setting doing nothing.
|
||||
- Fixed certain items causing the "analyzeitem" and "deconstructvalue" console commands to crash.
|
||||
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
v0.15.13.0
|
||||
@@ -502,9 +454,6 @@ Additions and changes:
|
||||
- Enabled NVidia Optimus on Windows.
|
||||
|
||||
Fixes:
|
||||
- Fixed crashing when an attack is applied on a character from a source other than another character, e.g. propeller (unstable only).
|
||||
- Fixed current_position_y output not working on nav terminals (unstable only).
|
||||
- Fixed fuel rods having a bullet as a contained indicator (unstable only).
|
||||
- Removed duplicate welcome messages from humpack's terminal.
|
||||
- Fixed start and spectate buttons shrinking in the server lobby every time they're hidden and re-enabled.
|
||||
- Fixed contained items inside contained items not moving when repositioning a container in the sub editor (e.g. when moving a weapon holder that contains a weapon with a magazine).
|
||||
@@ -548,7 +497,6 @@ Fixes:
|
||||
- The overdosed NPC in the "good samaritan" event can't die until the player has triggered the event (completing the event after the NPC had already died made no sense).
|
||||
- Fixed console errors when an item a bot has been ordered to target was removed between rounds (e.g. an ignore order targeting a mission item that gets removed at the end of the round).
|
||||
- Fixes to oxygen generator logic: the generator now periodically recalculates how to distribute the oxygen between the vents, as opposed to doing it once at the start of the round. Just doing it once caused issues if there were e.g. vents or doors that are initially open between the rooms.
|
||||
- Fixed characters sometimes getting "stuck" when swimming in partially filled multi-hull rooms. Happened because the bottom of the current hull was used as the "floor" if the actual floor was too far below, even if there was another hull below the current one, causing the ragdoll to switch to walking animation and being unable to move because it's not touching the floor (unstable only).
|
||||
- Fixed outpost events always unlocking the same escort mission.
|
||||
- The hints about flooded rooms and ballast flora aren't shown in ruins, wrecks or enemy subs.
|
||||
- Fixed "stowaway" event triggering an event cooldown, preventing monsters from spawning at the beginning of the round.
|
||||
|
||||
Reference in New Issue
Block a user