Build 0.20.0.0
This commit is contained in:
@@ -1026,7 +1026,7 @@ namespace Barotrauma.MapCreatures.Behavior
|
||||
branch.DamageVisualizationTimer = 1.0f;
|
||||
}
|
||||
|
||||
if (branch.IsRootGrowth && root != null && root.Health > 0.0f) { return; }
|
||||
if (branch.IsRootGrowth && root is { Health: > 0.0f }) { return; }
|
||||
|
||||
if (type != AttackType.Other && type != AttackType.CutFromRoot)
|
||||
{
|
||||
@@ -1035,7 +1035,7 @@ namespace Barotrauma.MapCreatures.Behavior
|
||||
}
|
||||
|
||||
if (GameMain.NetworkMember != null)
|
||||
{
|
||||
{
|
||||
// damage is handled server side
|
||||
if (GameMain.NetworkMember.IsClient)
|
||||
{
|
||||
@@ -1059,6 +1059,11 @@ namespace Barotrauma.MapCreatures.Behavior
|
||||
|
||||
if (type == AttackType.Fire)
|
||||
{
|
||||
if (attacker is not null)
|
||||
{
|
||||
damage *= 1f + attacker.GetStatValue(StatTypes.BallastFloraDamageMultiplier);
|
||||
}
|
||||
|
||||
if (IsInWater(branch))
|
||||
{
|
||||
damage *= 1f - SubmergedWaterResistance;
|
||||
@@ -1066,7 +1071,7 @@ namespace Barotrauma.MapCreatures.Behavior
|
||||
|
||||
if (defenseCooldown <= 0)
|
||||
{
|
||||
if (!(StateMachine.State is DefendWithPumpState))
|
||||
if (StateMachine.State is not DefendWithPumpState)
|
||||
{
|
||||
StateMachine.EnterState(new DefendWithPumpState(branch, ClaimedTargets, attacker));
|
||||
defenseCooldown = 180f;
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.MapCreatures.Behavior;
|
||||
using Barotrauma.Networking;
|
||||
using FarseerPhysics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.MapCreatures.Behavior;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -131,17 +130,23 @@ namespace Barotrauma
|
||||
if (damageSource is Item sourceItem)
|
||||
{
|
||||
var launcher = sourceItem.GetComponent<Projectile>()?.Launcher;
|
||||
displayRange *=
|
||||
1.0f
|
||||
+ sourceItem.GetQualityModifier(Quality.StatType.ExplosionRadius)
|
||||
displayRange *=
|
||||
1.0f
|
||||
+ sourceItem.GetQualityModifier(Quality.StatType.ExplosionRadius)
|
||||
+ (launcher?.GetQualityModifier(Quality.StatType.ExplosionRadius) ?? 0);
|
||||
Attack.DamageMultiplier *=
|
||||
1.0f
|
||||
Attack.DamageMultiplier *=
|
||||
1.0f
|
||||
+ sourceItem.GetQualityModifier(Quality.StatType.ExplosionDamage)
|
||||
+ (launcher?.GetQualityModifier(Quality.StatType.ExplosionDamage) ?? 0);
|
||||
Attack.SourceItem ??= sourceItem;
|
||||
}
|
||||
|
||||
if (attacker is not null)
|
||||
{
|
||||
displayRange *= 1f + attacker.GetStatValue(StatTypes.ExplosionRadiusMultiplier);
|
||||
Attack.DamageMultiplier *= 1f + attacker.GetStatValue(StatTypes.ExplosionDamageMultiplier);
|
||||
}
|
||||
|
||||
Vector2 cameraPos = GameMain.GameScreen.Cam.Position;
|
||||
float cameraDist = Vector2.Distance(cameraPos, worldPosition) / 2.0f;
|
||||
GameMain.GameScreen.Cam.Shake = cameraShake * Math.Max((cameraShakeRange - cameraDist) / cameraShakeRange, 0.0f);
|
||||
@@ -187,7 +192,7 @@ namespace Barotrauma
|
||||
var powerContainer = item.GetComponent<PowerContainer>();
|
||||
if (powerContainer != null)
|
||||
{
|
||||
powerContainer.Charge -= powerContainer.Capacity * EmpStrength * distFactor;
|
||||
powerContainer.Charge -= powerContainer.GetCapacity() * EmpStrength * distFactor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3015,6 +3015,7 @@ namespace Barotrauma
|
||||
var selectedLocation = allValidLocations.FirstOrDefault(l =>
|
||||
Vector2.Distance(l.Edge.Point1, l.Edge.Point2) is float edgeLength &&
|
||||
!l.Edge.OutsideLevel &&
|
||||
((l.Edge.Cell1?.IsDestructible ?? false) || (l.Edge.Cell2?.IsDestructible ?? false)) &&
|
||||
requiredAmount <= (int)Math.Floor(edgeLength / ((1.0f - maxResourceOverlap) * prefab.Size.X)));
|
||||
|
||||
|
||||
@@ -3905,7 +3906,7 @@ namespace Barotrauma
|
||||
|
||||
private bool HasEndOutpost()
|
||||
{
|
||||
if (preSelectedStartOutpost != null) { return true; }
|
||||
if (preSelectedEndOutpost != null) { return true; }
|
||||
//don't create an end outpost for locations
|
||||
if (LevelData.Type == LevelData.LevelType.Outpost) { return false; }
|
||||
if (EndLocation != null && !EndLocation.Type.HasOutpost) { return false; }
|
||||
@@ -4323,6 +4324,10 @@ namespace Barotrauma
|
||||
sp = corpsePoints.FirstOrDefault(sp => sp.AssignedJob == null) ?? pathPoints.FirstOrDefault(sp => sp.AssignedJob == null);
|
||||
// Deduce the job from the selected prefab
|
||||
selectedPrefab = GetCorpsePrefab(usedJobs);
|
||||
if (selectedPrefab != null)
|
||||
{
|
||||
job = selectedPrefab.GetJobPrefab();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (selectedPrefab == null) { continue; }
|
||||
|
||||
+28
-25
@@ -542,38 +542,41 @@ namespace Barotrauma
|
||||
GlobalForceDecreaseTimer = 0.0f;
|
||||
}
|
||||
|
||||
foreach (LevelObject obj in updateableObjects)
|
||||
if (updateableObjects is not null)
|
||||
{
|
||||
if (GameMain.NetworkMember is { IsServer: true })
|
||||
foreach (LevelObject obj in updateableObjects)
|
||||
{
|
||||
obj.NetworkUpdateTimer -= deltaTime;
|
||||
if (obj.NeedsNetworkSyncing && obj.NetworkUpdateTimer <= 0.0f)
|
||||
if (GameMain.NetworkMember is { IsServer: true })
|
||||
{
|
||||
GameMain.NetworkMember.CreateEntityEvent(this, new EventData(obj));
|
||||
obj.NeedsNetworkSyncing = false;
|
||||
obj.NetworkUpdateTimer = NetConfig.LevelObjectUpdateInterval;
|
||||
}
|
||||
}
|
||||
if (obj.Prefab.HideWhenBroken && obj.Health <= 0.0f) { continue; }
|
||||
|
||||
if (obj.Triggers != null)
|
||||
{
|
||||
obj.ActivePrefab = obj.Prefab;
|
||||
for (int i = 0; i < obj.Triggers.Count; i++)
|
||||
{
|
||||
obj.Triggers[i].Update(deltaTime);
|
||||
if (obj.Triggers[i].IsTriggered && obj.Prefab.OverrideProperties[i] != null)
|
||||
obj.NetworkUpdateTimer -= deltaTime;
|
||||
if (obj.NeedsNetworkSyncing && obj.NetworkUpdateTimer <= 0.0f)
|
||||
{
|
||||
obj.ActivePrefab = obj.Prefab.OverrideProperties[i];
|
||||
GameMain.NetworkMember.CreateEntityEvent(this, new EventData(obj));
|
||||
obj.NeedsNetworkSyncing = false;
|
||||
obj.NetworkUpdateTimer = NetConfig.LevelObjectUpdateInterval;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (obj.Prefab.HideWhenBroken && obj.Health <= 0.0f) { continue; }
|
||||
|
||||
if (obj.PhysicsBody != null)
|
||||
{
|
||||
if (obj.Prefab.PhysicsBodyTriggerIndex > -1) { obj.PhysicsBody.Enabled = obj.Triggers[obj.Prefab.PhysicsBodyTriggerIndex].IsTriggered; }
|
||||
/*obj.Position = new Vector3(obj.PhysicsBody.Position, obj.Position.Z);
|
||||
obj.Rotation = -obj.PhysicsBody.Rotation;*/
|
||||
if (obj.Triggers != null)
|
||||
{
|
||||
obj.ActivePrefab = obj.Prefab;
|
||||
for (int i = 0; i < obj.Triggers.Count; i++)
|
||||
{
|
||||
obj.Triggers[i].Update(deltaTime);
|
||||
if (obj.Triggers[i].IsTriggered && obj.Prefab.OverrideProperties[i] != null)
|
||||
{
|
||||
obj.ActivePrefab = obj.Prefab.OverrideProperties[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (obj.PhysicsBody != null)
|
||||
{
|
||||
if (obj.Prefab.PhysicsBodyTriggerIndex > -1) { obj.PhysicsBody.Enabled = obj.Triggers[obj.Prefab.PhysicsBodyTriggerIndex].IsTriggered; }
|
||||
/*obj.Position = new Vector3(obj.PhysicsBody.Position, obj.Position.Z);
|
||||
obj.Rotation = -obj.PhysicsBody.Rotation;*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ namespace Barotrauma
|
||||
foreach (var stockElement in storeElement.GetChildElements("stock"))
|
||||
{
|
||||
var identifier = stockElement.GetAttributeIdentifier("id", Identifier.Empty);
|
||||
if (identifier.IsEmpty || !(ItemPrefab.FindByIdentifier(identifier) is ItemPrefab prefab)) { continue; }
|
||||
if (identifier.IsEmpty || ItemPrefab.FindByIdentifier(identifier) is not ItemPrefab prefab) { continue; }
|
||||
int qty = stockElement.GetAttributeInt("qty", 0);
|
||||
if (qty < 1) { continue; }
|
||||
Stock.Add(new PurchasedItem(prefab, qty, buyer: null));
|
||||
@@ -157,7 +157,7 @@ namespace Barotrauma
|
||||
foreach (var childElement in element.GetChildElements("item"))
|
||||
{
|
||||
var id = childElement.GetAttributeIdentifier("id", Identifier.Empty);
|
||||
if (id.IsEmpty || !(ItemPrefab.FindByIdentifier(id) is ItemPrefab prefab)) { continue; }
|
||||
if (id.IsEmpty || ItemPrefab.FindByIdentifier(id) is not ItemPrefab prefab) { continue; }
|
||||
specials.Add(prefab);
|
||||
}
|
||||
return specials;
|
||||
@@ -240,7 +240,7 @@ namespace Barotrauma
|
||||
availableStock.Add(stockItem.ItemPrefab, weight);
|
||||
}
|
||||
DailySpecials.Clear();
|
||||
int extraSpecialSalesCount = Location.GetExtraSpecialSalesCount();
|
||||
int extraSpecialSalesCount = GetExtraSpecialSalesCount();
|
||||
for (int i = 0; i < Location.DailySpecialsCount + extraSpecialSalesCount; i++)
|
||||
{
|
||||
if (availableStock.None()) { break; }
|
||||
@@ -283,6 +283,17 @@ namespace Barotrauma
|
||||
}
|
||||
// Adjust by current location reputation
|
||||
price *= Location.GetStoreReputationModifier(true);
|
||||
|
||||
var characters = GameSession.GetSessionCrewCharacters(CharacterType.Both);
|
||||
if (characters.Any())
|
||||
{
|
||||
if (Location.Reputation?.Faction is { } faction && faction.IsAffiliated())
|
||||
{
|
||||
price *= 1f - characters.Max(static c => c.GetStatValue(StatTypes.StoreBuyMultiplierAffiliated));
|
||||
}
|
||||
price *= 1f - characters.Max(static c => c.GetStatValue(StatTypes.StoreBuyMultiplier));
|
||||
price *= 1f + characters.Max(c => item.Tags.Sum(tag => c.Info.GetSavedStatValue(StatTypes.StoreBuyMultiplier, tag)));
|
||||
}
|
||||
// Price should never go below 1 mk
|
||||
return Math.Max((int)price, 1);
|
||||
}
|
||||
@@ -303,6 +314,14 @@ namespace Barotrauma
|
||||
}
|
||||
// Adjust by current location reputation
|
||||
price *= Location.GetStoreReputationModifier(false);
|
||||
|
||||
var characters = GameSession.GetSessionCrewCharacters(CharacterType.Both);
|
||||
if (characters.Any())
|
||||
{
|
||||
price *= 1f + characters.Max(static c => c.GetStatValue(StatTypes.StoreSellMultiplier));
|
||||
price *= 1f + characters.Max(c => item.Tags.Sum(tag => c.Info.GetSavedStatValue(StatTypes.StoreSellMultiplier, tag)));
|
||||
}
|
||||
|
||||
// Price should never go below 1 mk
|
||||
return Math.Max((int)price, 1);
|
||||
}
|
||||
@@ -906,11 +925,17 @@ namespace Barotrauma
|
||||
|
||||
public LocationType GetLocationType()
|
||||
{
|
||||
if (IsCriticallyRadiated() && LocationType.Prefabs[Type.ReplaceInRadiation] is { } newLocationType)
|
||||
if (IsCriticallyRadiated() && !Type.ReplaceInRadiation.IsEmpty)
|
||||
{
|
||||
return newLocationType;
|
||||
if (LocationType.Prefabs.TryGet(Type.ReplaceInRadiation, out LocationType newLocationType))
|
||||
{
|
||||
return newLocationType;
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError($"Error when trying to get a new location type for an irradiated location - location type \"{newLocationType}\" not found.");
|
||||
}
|
||||
}
|
||||
|
||||
return Type;
|
||||
}
|
||||
|
||||
@@ -1119,7 +1144,7 @@ namespace Barotrauma
|
||||
public void UpdateStores()
|
||||
{
|
||||
// In multiplayer, stores should be updated by the server and loaded from save data by clients
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
|
||||
if (GameMain.NetworkMember is { IsClient: true }) { return; }
|
||||
if (Stores == null)
|
||||
{
|
||||
CreateStores();
|
||||
@@ -1161,13 +1186,10 @@ namespace Barotrauma
|
||||
stockToRemove.ForEach(i => stock.Remove(i));
|
||||
store.Stock.Clear();
|
||||
store.Stock.AddRange(stock);
|
||||
int extraSpecialSalesCount = GetExtraSpecialSalesCount();
|
||||
if (++StepsSinceSpecialsUpdated >= SpecialsUpdateInterval || store.DailySpecials.Count() != DailySpecialsCount + extraSpecialSalesCount)
|
||||
{
|
||||
store.GenerateSpecials();
|
||||
}
|
||||
store.GeneratePriceModifier();
|
||||
}
|
||||
|
||||
StepsSinceSpecialsUpdated++;
|
||||
foreach (var identifier in storesToRemove)
|
||||
{
|
||||
Stores.Remove(identifier);
|
||||
@@ -1178,6 +1200,20 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateSpecials()
|
||||
{
|
||||
if (GameMain.NetworkMember is { IsClient: true } || Stores is null) { return; }
|
||||
|
||||
int extraSpecialSalesCount = GetExtraSpecialSalesCount();
|
||||
|
||||
foreach (StoreInfo store in Stores.Values)
|
||||
{
|
||||
if (StepsSinceSpecialsUpdated < SpecialsUpdateInterval && store.DailySpecials.Count == DailySpecialsCount + extraSpecialSalesCount) { continue; }
|
||||
|
||||
store.GenerateSpecials();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateStoreIdentifiers()
|
||||
{
|
||||
StoreIdentifiers.Clear();
|
||||
@@ -1249,7 +1285,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public int GetExtraSpecialSalesCount()
|
||||
public static int GetExtraSpecialSalesCount()
|
||||
{
|
||||
var characters = GameSession.GetSessionCrewCharacters(CharacterType.Both);
|
||||
if (!characters.Any()) { return 0; }
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace Barotrauma
|
||||
private set;
|
||||
}
|
||||
|
||||
public string ReplaceInRadiation { get; }
|
||||
public Identifier ReplaceInRadiation { get; }
|
||||
|
||||
public Sprite Sprite { get; private set; }
|
||||
public Sprite RadiationSprite { get; }
|
||||
@@ -108,7 +108,7 @@ namespace Barotrauma
|
||||
|
||||
HideEntitySubcategories = element.GetAttributeStringArray("hideentitysubcategories", Array.Empty<string>()).ToList();
|
||||
|
||||
ReplaceInRadiation = element.GetAttributeString(nameof(ReplaceInRadiation).ToLower(), "");
|
||||
ReplaceInRadiation = element.GetAttributeIdentifier(nameof(ReplaceInRadiation), Identifier.Empty);
|
||||
|
||||
string teamStr = element.GetAttributeString("outpostteam", "FriendlyNPC");
|
||||
Enum.TryParse(teamStr, out OutpostTeam);
|
||||
|
||||
@@ -560,6 +560,42 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
//make sure the location at the right side of the gate between biomes isn't a dead-end
|
||||
//those may sometimes generate if all the connections of the right-side location lead to the previous biome
|
||||
//(i.e. a situation where the adjacent locations happen to be at the left side of the border of the biomes, see see Regalis11/Barotrauma#10047)
|
||||
for (int i = 0; i < Connections.Count; i++)
|
||||
{
|
||||
var connection = Connections[i];
|
||||
if (!connection.Locked) { continue; }
|
||||
var rightMostLocation =
|
||||
connection.Locations[0].MapPosition.X > connection.Locations[1].MapPosition.X ?
|
||||
connection.Locations[0] :
|
||||
connection.Locations[1];
|
||||
|
||||
//if there's only one connection (= the connection between biomes), create a new connection to the closest location to the right
|
||||
if (rightMostLocation.Connections.Count == 1)
|
||||
{
|
||||
Location closestLocation = null;
|
||||
float closestDist = float.PositiveInfinity;
|
||||
foreach (Location otherLocation in Locations)
|
||||
{
|
||||
if (otherLocation == rightMostLocation || otherLocation.MapPosition.X < rightMostLocation.MapPosition.X) { continue; }
|
||||
float dist = Vector2.DistanceSquared(rightMostLocation.MapPosition, otherLocation.MapPosition);
|
||||
if (dist < closestDist || closestLocation == null)
|
||||
{
|
||||
closestLocation = otherLocation;
|
||||
closestDist = dist;
|
||||
}
|
||||
}
|
||||
|
||||
var newConnection = new LocationConnection(rightMostLocation, closestLocation);
|
||||
rightMostLocation.Connections.Add(newConnection);
|
||||
closestLocation.Connections.Add(newConnection);
|
||||
Connections.Add(newConnection);
|
||||
GenerateLocationConnectionVisuals(newConnection);
|
||||
}
|
||||
}
|
||||
|
||||
//remove orphans
|
||||
Locations.RemoveAll(l => !Connections.Any(c => c.Locations.Contains(l)));
|
||||
|
||||
@@ -606,7 +642,9 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
partial void GenerateLocationConnectionVisuals();
|
||||
partial void GenerateAllLocationConnectionVisuals();
|
||||
|
||||
partial void GenerateLocationConnectionVisuals(LocationConnection connection);
|
||||
|
||||
private int GetZoneIndex(float xPos)
|
||||
{
|
||||
@@ -944,6 +982,16 @@ namespace Barotrauma
|
||||
ProgressWorld();
|
||||
}
|
||||
|
||||
// always update specials every step
|
||||
for (int i = 0; i < Math.Max(1, steps); i++)
|
||||
{
|
||||
foreach (Location location in Locations)
|
||||
{
|
||||
if (!location.Discovered) { continue; }
|
||||
location.UpdateSpecials();
|
||||
}
|
||||
}
|
||||
|
||||
Radiation?.OnStep(steps);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ namespace Barotrauma
|
||||
public bool DisplayNonEmpty { get; } = false;
|
||||
public Identifier StoreIdentifier { get; }
|
||||
|
||||
public bool RequiresUnlock { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Used when both <see cref="MinAvailableAmount"/> and <see cref="MaxAvailableAmount"/> are set to 0.
|
||||
/// </summary>
|
||||
@@ -48,6 +50,7 @@ namespace Barotrauma
|
||||
int maxAmount = GetMaxAmount(element);
|
||||
maxAmount = Math.Min(maxAmount, CargoManager.MaxQuantity);
|
||||
MaxAvailableAmount = Math.Max(maxAmount, MinAvailableAmount);
|
||||
RequiresUnlock = element.GetAttributeBool("requiresunlock", false);
|
||||
}
|
||||
|
||||
public PriceInfo(int price, bool canBeBought,
|
||||
|
||||
Reference in New Issue
Block a user