Build 0.20.7.0

This commit is contained in:
Markus Isberg
2022-11-18 18:13:38 +02:00
parent 8c8fd865c5
commit ecb6d40b4b
111 changed files with 1346 additions and 701 deletions
@@ -276,7 +276,7 @@ namespace Barotrauma.Items.Components
}
}
//get all walls within range
//get all walls within range the arc could potentially hit
List<Entity> entitiesInRange = new List<Entity>(100);
foreach (Structure structure in Structure.WallList)
{
@@ -284,10 +284,10 @@ namespace Barotrauma.Items.Components
if (structure.Submarine != null&& !submarinesInRange.Contains(structure.Submarine)) { continue; }
var structureWorldRect = structure.WorldRect;
if (worldPosition.X < structureWorldRect.X - range) continue;
if (worldPosition.X > structureWorldRect.Right + range) continue;
if (worldPosition.Y > structureWorldRect.Y + range) continue;
if (worldPosition.Y < structureWorldRect.Y -structureWorldRect.Height - range) continue;
if (worldPosition.X < structureWorldRect.X - range) { continue; }
if (worldPosition.X > structureWorldRect.Right + range) { continue; }
if (worldPosition.Y > structureWorldRect.Y + range) { continue; }
if (worldPosition.Y < structureWorldRect.Y - structureWorldRect.Height - range) { continue; }
if (structure.Submarine != null)
{
@@ -317,6 +317,7 @@ namespace Barotrauma.Items.Components
nodes.Add(new Node(worldPosition, -1));
}
//get all characters within range the arc could potentially hit
float totalRange = RaycastRange + range;
foreach (Character character in Character.CharacterList)
{
@@ -325,11 +326,20 @@ namespace Barotrauma.Items.Components
if (OutdoorsOnly && character.Submarine != null) { continue; }
if (character.Submarine != null && !submarinesInRange.Contains(character.Submarine)) { continue; }
if (Vector2.DistanceSquared(character.WorldPosition, worldPosition) < totalRange * totalRange * RangeMultiplierInWalls ||
(RaycastRange > 0.0f && MathUtils.LineToPointDistanceSquared(worldPosition, item.WorldPosition, character.WorldPosition) < range * range * RangeMultiplierInWalls))
if (Vector2.DistanceSquared(character.WorldPosition, worldPosition) < totalRange * totalRange * RangeMultiplierInWalls)
{
entitiesInRange.Add(character);
charactersInRange.Add((character, nodes[0]));
}
//if the weapon does a raycast, check distance to the ray too (not just the end of the ray)
if (RaycastRange > 0)
{
float distSqr = MathUtils.LineSegmentToPointDistanceSquared(worldPosition, item.WorldPosition, character.WorldPosition);
//if the distance from the initial raycast to the character is small (e.g. goes through the character), we know it must hit
if (distSqr < range * range * RangeMultiplierInWalls)
{
if (!entitiesInRange.Contains(character)) { entitiesInRange.Add(character); }
charactersInRange.Add((character, nodes.First()));
}
}
}
@@ -378,7 +388,7 @@ namespace Barotrauma.Items.Components
}
else if (entitiesInRange[i] is Character character)
{
dist = Vector2.Distance(character.WorldPosition, currPos);
dist = MathUtils.LineSegmentToPointDistanceSquared(currPos, nodes[parentNodeIndex].WorldPosition, character.WorldPosition);
}
if (dist < closestDist)
@@ -494,17 +504,31 @@ namespace Barotrauma.Items.Components
if (IgnoreUser && character == user) { continue; }
if (OutdoorsOnly && character.Submarine != null) { continue; }
Vector2 characterMin = new Vector2(character.AnimController.Limbs.Min(l => l.WorldPosition.X), character.AnimController.Limbs.Min(l => l.WorldPosition.Y));
Vector2 characterMax = new Vector2(character.AnimController.Limbs.Max(l => l.WorldPosition.X), character.AnimController.Limbs.Max(l => l.WorldPosition.Y));
if (targetStructure.IsHorizontal)
{
if (otherEntity.WorldPosition.X < targetStructure.WorldRect.X) { continue; }
if (otherEntity.WorldPosition.X > targetStructure.WorldRect.Right) { continue; }
if (Math.Abs(otherEntity.WorldPosition.Y - targetStructure.WorldPosition.Y) > currentRange) { continue; }
if (characterMax.X < targetStructure.WorldRect.X) { continue; }
if (characterMin.X > targetStructure.WorldRect.Right) { continue; }
if (Math.Abs(characterMin.Y - targetStructure.WorldPosition.Y) > currentRange &&
Math.Abs(characterMax.Y - targetStructure.WorldPosition.Y) > currentRange)
{
continue;
}
}
else
{
if (otherEntity.WorldPosition.Y < targetStructure.WorldRect.Y - targetStructure.Rect.Height) { continue; }
if (otherEntity.WorldPosition.Y > targetStructure.WorldRect.Y) { continue; }
if (Math.Abs(otherEntity.WorldPosition.X - targetStructure.WorldPosition.X) > currentRange) { continue; }
if (characterMax.Y < targetStructure.WorldRect.Y - targetStructure.Rect.Height) { continue; }
if (characterMin.Y > targetStructure.WorldRect.Y) { continue; }
if (Math.Abs(characterMin.X - targetStructure.WorldPosition.X) > currentRange &&
Math.Abs(characterMax.X - targetStructure.WorldPosition.X) > currentRange)
{
continue;
}
}
if (!charactersInRange.Any(c => c.character == character))
{
charactersInRange.Add((character, nodes[parentNodeIndex]));
}
float closestNodeDistSqr = float.MaxValue;
int closestNodeIndex = -1;
@@ -12,7 +12,7 @@ namespace Barotrauma.Items.Components
{
public enum UseEnvironment
{
Air, Water, Both
Air, Water, Both, None
};
private float useState;
@@ -44,6 +44,7 @@ namespace Barotrauma.Items.Components
{
if (character == null || character.Removed) { return false; }
if (!character.IsKeyDown(InputType.Aim) || character.Stun > 0.0f) { return false; }
if (UsableIn == UseEnvironment.None) { return false; }
IsActive = true;
useState = 0.1f;
@@ -476,6 +476,7 @@ namespace Barotrauma.Items.Components
{
foreach (Item item in Inventory.AllItemsMod)
{
item.ApplyStatusEffects(ActionType.OnSuccess, 1.0f, ownerCharacter);
item.ApplyStatusEffects(ActionType.OnUse, 1.0f, ownerCharacter);
item.GetComponent<GeneticMaterial>()?.Equip(ownerCharacter);
autoInjectCooldown = AutoInjectInterval;
@@ -450,6 +450,7 @@ namespace Barotrauma.Items.Components
public override bool Select(Character activator)
{
if (activator == null || activator.Removed) { return false; }
if (Item.Condition <= 0.0f && !UpdateWhenInactive) { return false; }
if (UsableIn == UseEnvironment.Water && !activator.AnimController.InWater ||
UsableIn == UseEnvironment.Air && activator.AnimController.InWater)
@@ -15,6 +15,8 @@ namespace Barotrauma.Items.Components
{
private ImmutableDictionary<uint, FabricationRecipe> fabricationRecipes; //this is not readonly because tutorials fuck this up!!!!
private const int MaxAmountToFabricate = 99;
private FabricationRecipe fabricatedItem;
private float timeUntilReady;
private float requiredTime;
@@ -39,6 +41,16 @@ namespace Barotrauma.Items.Components
[Serialize(1.0f, IsPropertySaveable.Yes)]
public float SkillRequirementMultiplier { get; set; }
private int amountToFabricate;
[Serialize(1, IsPropertySaveable.Yes)]
public int AmountToFabricate
{
get { return amountToFabricate; }
set { amountToFabricate = MathHelper.Clamp(value, 1, MaxAmountToFabricate); }
}
private int amountRemaining;
private const float TinkeringSpeedIncrease = 2.5f;
private enum FabricatorState
@@ -183,16 +195,20 @@ namespace Barotrauma.Items.Components
if (selectedItem == null) { return; }
if (!outputContainer.Inventory.CanBePut(selectedItem.TargetItem, selectedItem.OutCondition * selectedItem.TargetItem.Health)) { return; }
#if CLIENT
itemList.Enabled = false;
activateButton.Text = TextManager.Get("FabricatorCancel");
#endif
IsActive = true;
this.user = user;
fabricatedItem = selectedItem;
RefreshAvailableIngredients();
#if CLIENT
itemList.Enabled = false;
if (amountInput != null)
{
amountInput.Enabled = false;
}
RefreshActivateButtonText();
#endif
bool isClient = GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient;
if (!isClient)
{
@@ -249,10 +265,11 @@ namespace Barotrauma.Items.Components
}
#elif CLIENT
itemList.Enabled = true;
if (activateButton != null)
if (amountInput != null)
{
activateButton.Text = TextManager.Get(CreateButtonText);
amountInput.Enabled = true;
}
RefreshActivateButtonText();
#endif
fabricatedItem = null;
}
@@ -518,20 +535,16 @@ namespace Barotrauma.Items.Components
}
}
//disabled "continuous fabrication" for now
//before we enable it, there should be some UI controls for fabricating a specific number of items
/*var prevFabricatedItem = fabricatedItem;
var prevFabricatedItem = fabricatedItem;
var prevUser = user;
CancelFabricating();
if (CanBeFabricated(prevFabricatedItem))
amountRemaining--;
if (amountRemaining > 0 && CanBeFabricated(prevFabricatedItem, availableIngredients, prevUser))
{
//keep fabricating if we can fabricate more
StartFabricating(prevFabricatedItem, prevUser, addToServerLog: false);
}*/
CancelFabricating();
}
}
}
@@ -594,7 +607,15 @@ namespace Barotrauma.Items.Components
private bool CanBeFabricated(FabricationRecipe fabricableItem, IReadOnlyDictionary<Identifier, List<Item>> availableIngredients, Character character)
{
if (fabricableItem == null) { return false; }
if (fabricableItem.RequiresRecipe && (character == null || !character.HasRecipeForItem(fabricableItem.TargetItem.Identifier))) { return false; }
if (fabricableItem.RequiresRecipe)
{
if (character == null) { return false; }
if (!character.HasRecipeForItem(fabricableItem.TargetItem.Identifier) &&
GameSession.GetSessionCrewCharacters(CharacterType.Bot).None(c => c.HasRecipeForItem(fabricableItem.TargetItem.Identifier)))
{
return false;
}
}
if (fabricableItem.RequiredMoney > 0)
{
@@ -151,7 +151,6 @@ namespace Barotrauma.Items.Components
set
{
bool changed = currentMode != value;
currentMode = value;
#if CLIENT
if (changed) { prevPassivePingRadius = float.MaxValue; }
@@ -1,6 +1,7 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
@@ -9,14 +10,6 @@ namespace Barotrauma.Items.Components
{
public const int MaxQuality = 3;
public static readonly float[] QualityCommonnesses = new float[]
{
0.8f,
0.15f,
0.045f,
0.005f,
};
public enum StatType
{
Condition,
@@ -81,5 +74,29 @@ namespace Barotrauma.Items.Components
if (!statValues.ContainsKey(statType)) { return 0.0f; }
return statValues[statType] * qualityLevel;
}
/// <summary>
/// Get a random quality for an item spawning in some sub, taking into account the type of the submarine and the difficulty of the current level
/// (high-quality items become more common as difficulty increases)
/// </summary>
public static int GetSpawnedItemQuality(Submarine submarine, Level level, Rand.RandSync randSync = Rand.RandSync.ServerAndClient)
{
if (submarine?.Info == null || level == null || submarine.Info.Type == SubmarineType.Player) { return 0; }
float difficultyFactor = MathHelper.Clamp(level.Difficulty, 0.0f, 1.0f);
return ToolBox.SelectWeightedRandom(Enumerable.Range(0, MaxQuality + 1), q => GetCommonness(q, difficultyFactor), randSync);
static float GetCommonness(int quality, float difficultyFactor)
{
return quality switch
{
0 => 1,
1 => MathHelper.Lerp(0.0f, 1f, difficultyFactor),
2 => MathHelper.Lerp(0.0f, 1f, Math.Max(difficultyFactor-0.15f, 0f)), //15 difficulty transition to next biome - unlock Excellent loot
3 => MathHelper.Lerp(0.0f, 1f, Math.Max(difficultyFactor-0.35f, 0f)), //35 difficulty transition to next biome - unlock Masterwork loot
_ => 0.0f,
};
}
}
}
}