Unstable 0.1300.0.7

This commit is contained in:
Markus Isberg
2021-04-07 15:24:22 +03:00
parent 96b2184811
commit 538c3dbfc3
47 changed files with 246 additions and 103 deletions
@@ -765,7 +765,7 @@ namespace Barotrauma
{
var location = memory.Location;
float dist = Vector2.DistanceSquared(WorldPosition, location);
if (dist < 50 * 50)
if (dist < 50 * 50 || !IsPositionInsideAllowedZone(WorldPosition, out _))
{
// Target is gone
ResetAITarget();
@@ -1848,49 +1848,68 @@ namespace Barotrauma
public static bool IsItemOperatedByAnother(Character character, ItemComponent target, out Character operatingCharacter)
{
operatingCharacter = null;
if (character == null) { return false; }
if (target?.Item == null) { return false; }
bool isOrder = IsOrderedToOperateThis(character.AIController);
foreach (var c in Character.CharacterList)
{
if (character == null) { continue; }
if (c == character) { continue; }
if (c.IsDead || c.IsIncapacitated) { continue; }
if (!IsFriendly(character, c, onlySameTeam: true)) { continue; }
operatingCharacter = c;
if (c.AIController is HumanAIController controllingHumanAi)
if (c.IsPlayer)
{
Item otherTarget = controllingHumanAi.objectiveManager.GetActiveObjective<AIObjectiveOperateItem>()?.Component.Item ?? c.SelectedConstruction;
if (otherTarget != target.Item) { continue; }
// If the other character is player, don't try to operate
if (c.IsPlayer) { return true; }
// If the other character is ordered to operate the item, let him do it
if (controllingHumanAi.ObjectiveManager.IsCurrentOrder<AIObjectiveOperateItem>())
if (c.SelectedConstruction == target.Item)
{
// If the other character is player, don't try to operate
return true;
}
}
else if (c.AIController is HumanAIController operatingAI)
{
if (operatingAI.ObjectiveManager.Objectives.None(o => o is AIObjectiveOperateItem operateObjective && operateObjective.Component.Item == target.Item))
{
// Not targeting the same item.
continue;
}
bool isTargetOrdered = IsOrderedToOperateThis(c.AIController);
if (!isOrder && isTargetOrdered)
{
// If the other bot is ordered to operate the item, let him do it, unless we are ordered too
return true;
}
else
{
if (character == null)
if (isOrder && !isTargetOrdered)
{
return true;
}
else if (target is Steering)
{
// Steering is hard-coded -> cannot use the required skills collection defined in the xml
return character.GetSkillLevel("helm") <= c.GetSkillLevel("helm");
// We are ordered and the target is not -> allow to operate
continue;
}
else
{
return target.DegreeOfSuccess(character) <= target.DegreeOfSuccess(c);
if (!isTargetOrdered && operatingAI.ObjectiveManager.CurrentOrder == operatingAI.ObjectiveManager.CurrentObjective)
{
// The other bot is ordered to do something else
continue;
}
if (target is Steering)
{
// Steering is hard-coded -> cannot use the required skills collection defined in the xml
if (character.GetSkillLevel("helm") <= c.GetSkillLevel("helm"))
{
return true;
}
}
else if (target.DegreeOfSuccess(character) <= target.DegreeOfSuccess(c))
{
return true;
}
}
}
}
else
{
return c.SelectedConstruction == target.Item;
}
}
return false;
bool IsOrderedToOperateThis(AIController ai) => ai is HumanAIController humanAI && humanAI.ObjectiveManager.CurrentOrder is AIObjectiveOperateItem operateObjective && operateObjective.Component.Item == target.Item;
}
#region Wrappers
@@ -415,7 +415,7 @@ namespace Barotrauma
#if DEBUG
DebugConsole.NewMessage($"{character.Name}: Get item failed to reach {moveToTarget}", Color.Yellow);
#endif
if (character.IsOnPlayerTeam && objectiveManager.CurrentOrder != null)
if (character.IsOnPlayerTeam && objectiveManager.CurrentOrder == objectiveManager.CurrentObjective)
{
string TargetName = (moveToTarget as MapEntity)?.Name ?? (moveToTarget as Character)?.Name ?? moveToTarget.ToString();
string msg = TargetName == null ? TextManager.Get("dialogcannotreachtarget", true) : TextManager.GetWithVariable("dialogcannotreachtarget", "[name]", TargetName, formatCapitals: !(moveToTarget is Character));
@@ -147,7 +147,7 @@ namespace Barotrauma
#if DEBUG
DebugConsole.NewMessage($"{character.Name}: Cannot reach the target: {Target}", Color.Yellow);
#endif
if (character.IsOnPlayerTeam && objectiveManager.CurrentOrder != null && DialogueIdentifier != null && SpeakIfFails)
if (character.IsOnPlayerTeam && objectiveManager.CurrentOrder == objectiveManager.CurrentObjective && DialogueIdentifier != null && SpeakIfFails)
{
string msg = TargetName == null ? TextManager.Get(DialogueIdentifier, true) : TextManager.GetWithVariable(DialogueIdentifier, "[name]", TargetName, formatCapitals: !(Target is Character));
if (msg != null)
@@ -132,7 +132,13 @@ namespace Barotrauma
}
var order = new Order(orderPrefab, item ?? character.CurrentHull as Entity, orderPrefab.GetTargetItemComponent(item), orderGiver: character);
if (order == null) { continue; }
if (autonomousObjective.ignoreAtOutpost && Level.IsLoadedOutpost && character.TeamID != CharacterTeamType.FriendlyNPC) { continue; }
if (autonomousObjective.ignoreAtOutpost && Level.IsLoadedOutpost && character.TeamID != CharacterTeamType.FriendlyNPC)
{
if (Submarine.MainSub != null && Submarine.MainSub.DockedTo.None(s => s.TeamID != CharacterTeamType.FriendlyNPC && s.TeamID != character.TeamID))
{
continue;
}
}
var objective = CreateObjective(order, autonomousObjective.option, character, isAutonomous: true, autonomousObjective.priorityModifier);
if (objective != null && objective.CanBeCompleted)
{
@@ -121,7 +121,7 @@ namespace Barotrauma
{
float value = CumulatedDevotion + (AIObjectiveManager.LowestOrderPriority * PriorityModifier);
float max = AIObjectiveManager.LowestOrderPriority - 1;
if (reactor != null && reactor.PowerOn && Option == "powerup")
if (reactor != null && reactor.PowerOn && reactor.FissionRate > 1 && Option == "powerup")
{
// Decrease the priority when targeting a reactor that is already on.
value /= 2;
@@ -1343,6 +1343,22 @@ namespace Barotrauma
/// </summary>
public float SpeedMultiplier { get; private set; } = 1;
private double propulsionSpeedMultiplierLastSet;
private float propulsionSpeedMultiplier;
/// <summary>
/// Can be used to modify the speed at which Propulsion ItemComponents move the character via StatusEffects (e.g. heavy suit can slow down underwater scooters)
/// </summary>
public float PropulsionSpeedMultiplier
{
get { return propulsionSpeedMultiplier; }
set
{
propulsionSpeedMultiplier = value;
propulsionSpeedMultiplierLastSet = Timing.TotalTime;
}
}
public void StackSpeedMultiplier(float val)
{
if (val < 1f)
@@ -1365,6 +1381,10 @@ namespace Barotrauma
{
greatestPositiveSpeedMultiplier = 1f;
greatestNegativeSpeedMultiplier = 1f;
if (Timing.TotalTime > propulsionSpeedMultiplierLastSet + 0.1)
{
propulsionSpeedMultiplier = 1.0f;
}
}
private float greatestNegativeHealthMultiplier = 1f;
@@ -3420,6 +3440,7 @@ namespace Barotrauma
if (statusEffect.type != actionType) { continue; }
if (statusEffect.type == ActionType.OnDamaged)
{
if (LastDamage.Afflictions == null || LastDamage.Afflictions.None(a => a.Prefab.AfflictionType == "damage")) { continue; }
if (statusEffect.OnlyPlayerTriggered)
{
if (LastAttacker == null || !LastAttacker.IsPlayer)
@@ -1127,6 +1127,7 @@ namespace Barotrauma
if (statusEffect.type != actionType) { continue; }
if (statusEffect.type == ActionType.OnDamaged)
{
if (character.LastDamage.Afflictions == null || character.LastDamage.Afflictions.None(a => a.Prefab.AfflictionType == "damage")) { continue; }
if (statusEffect.OnlyPlayerTriggered)
{
if (character.LastAttacker == null || !character.LastAttacker.IsPlayer)
@@ -26,7 +26,6 @@ namespace Barotrauma
public override void Update(float deltaTime)
{
if (isFinished) { return; }
GameMain.GameSession?.Map?.CurrentLocation?.Connections.ForEach(c => c.Locked = false);
if (GameMain.GameSession?.Map?.CurrentLocation?.Connections != null)
{
foreach (LocationConnection connection in GameMain.GameSession?.Map?.CurrentLocation?.Connections)
@@ -418,6 +418,7 @@ namespace Barotrauma
List<Pair<EventPrefab, float>> unusedEvents = new List<Pair<EventPrefab, float>>(suitablePrefabs);
for (int j = 0; j < eventSet.EventCount; j++)
{
if (unusedEvents.All(e => CalculateCommonness(e) <= 0.0f)) { break; }
var eventPrefab = ToolBox.SelectWeightedRandom(unusedEvents, unusedEvents.Select(e => CalculateCommonness(e)).ToList(), rand);
if (eventPrefab != null)
{
@@ -100,7 +100,7 @@ namespace Barotrauma
{
spawnPos = new Vector2(
MathHelper.Clamp(wp.WorldPosition.X + Rand.Range(-200, 200), wp.CurrentHull.WorldRect.X, wp.CurrentHull.WorldRect.Right),
wp.CurrentHull.WorldRect.Y - wp.CurrentHull.Rect.Height + 10.0f);
wp.CurrentHull.WorldRect.Y - wp.CurrentHull.Rect.Height + 16.0f);
}
var item = new Item(itemPrefab, spawnPos, null);
items.Add(item);
@@ -478,13 +478,6 @@ namespace Barotrauma
}
if (GameMode is MultiPlayerCampaign mpCampaign)
{
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
{
mpCampaign.CargoManager.CreatePurchasedItems();
#if SERVER
mpCampaign.SendCrewState(null, default, null);
#endif
}
mpCampaign.UpgradeManager.ApplyUpgrades();
mpCampaign.UpgradeManager.SanityCheckUpgrades(Submarine);
}
@@ -41,25 +41,25 @@ namespace Barotrauma.Items.Components
public override bool Use(float deltaTime, Character character = null)
{
if (character == null || character.Removed) return false;
if (!character.IsKeyDown(InputType.Aim) || character.Stun > 0.0f) return false;
if (!character.IsKeyDown(InputType.Aim) || character.Stun > 0.0f) { return false; }
IsActive = true;
useState = 0.1f;
if (character.AnimController.InWater)
{
if (UsableIn == UseEnvironment.Air) return true;
if (UsableIn == UseEnvironment.Air) { return true; }
}
else
{
if (UsableIn == UseEnvironment.Water) return true;
if (UsableIn == UseEnvironment.Water) { return true; }
}
Vector2 dir = Vector2.Normalize(character.CursorPosition - character.Position);
//move upwards if the cursor is at the position of the character
if (!MathUtils.IsValid(dir)) dir = Vector2.UnitY;
Vector2 propulsion = dir * Force;
Vector2 propulsion = dir * Force * character.PropulsionSpeedMultiplier;
if (character.AnimController.InWater) character.AnimController.TargetMovement = dir;
@@ -333,7 +333,7 @@ namespace Barotrauma.Items.Components
if (item.CurrentHull != null)
{
var aiTarget = item.CurrentHull.AiTarget;
if (aiTarget != null)
if (aiTarget != null && MaxPowerOutput > 0)
{
float range = Math.Abs(currPowerConsumption) / MaxPowerOutput;
float noise = MathHelper.Lerp(aiTarget.MinSoundRange, aiTarget.MaxSoundRange, range);
@@ -341,7 +341,7 @@ namespace Barotrauma.Items.Components
}
}
if (item.AiTarget != null)
if (item.AiTarget != null && MaxPowerOutput > 0)
{
var aiTarget = item.AiTarget;
float range = Math.Abs(currPowerConsumption) / MaxPowerOutput;
@@ -711,7 +711,7 @@ namespace Barotrauma.Items.Components
steeringAdjustSpeed = DefaultSteeringAdjustSpeed;
steeringInput = XMLExtensions.ParseVector2(signal.value, errorMessages: false);
steeringInput.X = MathHelper.Clamp(steeringInput.X, -100.0f, 100.0f);
steeringInput.Y = MathHelper.Clamp(steeringInput.Y, -100.0f, 100.0f);
steeringInput.Y = MathHelper.Clamp(-steeringInput.Y, -100.0f, 100.0f);
}
else
{
@@ -1,13 +1,10 @@
using FarseerPhysics;
using Barotrauma.IO;
using Barotrauma.Items.Components;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using Barotrauma.IO;
using System.Xml.Linq;
using System.Linq;
using Barotrauma.Items.Components;
using Barotrauma.Extensions;
using Voronoi2;
using System.Xml.Linq;
namespace Barotrauma
{
@@ -1077,7 +1074,10 @@ namespace Barotrauma
priceInfo = null;
if (location?.Type == null) { return false; }
priceInfo = GetPriceInfo(location);
return priceInfo != null && priceInfo.CanBeBought;
return
priceInfo != null &&
priceInfo.CanBeBought &&
(location.LevelData?.Difficulty ?? 0) >= priceInfo.MinLevelDifficulty;
}
public static ItemPrefab Find(string name, string identifier)
@@ -419,7 +419,7 @@ namespace Barotrauma
int zone1 = GetZoneIndex(Connections[i].Locations[0].MapPosition.X);
int zone2 = GetZoneIndex(Connections[i].Locations[1].MapPosition.X);
if (zone1 == zone2) { continue; }
if (zone2 == generationParams.DifficultyZones) { continue; }
if (zone1 == generationParams.DifficultyZones || zone2 == generationParams.DifficultyZones) { continue; }
if (!connectionsBetweenZones.Contains(Connections[i]))
{
@@ -464,7 +464,10 @@ namespace Barotrauma
foreach (Location location in Locations)
{
location.LevelData = new LevelData(location);
location.LevelData = new LevelData(location)
{
Difficulty = MathHelper.Clamp(location.MapPosition.X / Width * 100, 0.0f, 100.0f)
};
if (location.Type.MissionIdentifiers.Any())
{
location.UnlockMissionByIdentifier(location.Type.MissionIdentifiers.GetRandom());
@@ -20,15 +20,20 @@ namespace Barotrauma
/// Can the item be a Daily Special or a Requested Good
/// </summary>
public readonly bool CanBeSpecial;
/// <summary>
/// The item isn't available in stores unless the level's difficulty is above this value
/// </summary>
public readonly int MinLevelDifficulty;
/// <summary>
/// Support for the old style of determining item prices
/// when there were individual Price elements for each location type
/// where the item was for sale.
/// </summary>
public PriceInfo (XElement element)
public PriceInfo(XElement element)
{
Price = element.GetAttributeInt("buyprice", 0);
MinLevelDifficulty = element.GetAttributeInt("minleveldifficulty", 0);
CanBeBought = true;
var minAmount = GetMinAmount(element);
MinAvailableAmount = Math.Min(minAmount, CargoManager.MaxQuantity);
@@ -37,13 +42,14 @@ namespace Barotrauma
MaxAvailableAmount = Math.Max(maxAmount, MinAvailableAmount);
}
public PriceInfo(int price, bool canBeBought, int minAmount = 0, int maxAmount = 0, bool canBeSpecial = true)
public PriceInfo(int price, bool canBeBought, int minAmount = 0, int maxAmount = 0, bool canBeSpecial = true, int minLevelDifficulty = 0)
{
Price = price;
CanBeBought = canBeBought;
MinAvailableAmount = Math.Min(minAmount, CargoManager.MaxQuantity);
maxAmount = Math.Min(maxAmount, CargoManager.MaxQuantity);
MaxAvailableAmount = Math.Max(maxAmount, minAmount);
MinLevelDifficulty = minLevelDifficulty;
CanBeSpecial = canBeSpecial;
}
@@ -54,6 +60,7 @@ namespace Barotrauma
var soldByDefault = element.GetAttributeBool("soldbydefault", true);
var minAmount = GetMinAmount(element);
var maxAmount = GetMaxAmount(element);
var minLevelDifficulty = element.GetAttributeInt("minleveldifficulty", 0);
var canBeSpecial = element.GetAttributeBool("canbespecial", true);
var priceInfos = new List<Tuple<string, PriceInfo>>();
@@ -65,14 +72,16 @@ namespace Barotrauma
new PriceInfo(price: (int)(priceMultiplier * basePrice), canBeBought: sold,
minAmount: sold ? GetMinAmount(childElement, minAmount) : 0,
maxAmount: sold ? GetMaxAmount(childElement, maxAmount) : 0,
canBeSpecial: canBeSpecial)));
canBeSpecial,
childElement.GetAttributeInt("minleveldifficulty", minLevelDifficulty))));
}
var canBeBoughtAtOtherLocations = soldByDefault && element.GetAttributeBool("soldeverywhere", true);
defaultPrice = new PriceInfo(basePrice, canBeBoughtAtOtherLocations,
minAmount: canBeBoughtAtOtherLocations ? minAmount : 0,
maxAmount: canBeBoughtAtOtherLocations ? maxAmount : 0,
canBeSpecial: canBeSpecial);
canBeSpecial,
minLevelDifficulty);
return priceInfos;
}
@@ -819,16 +819,12 @@ namespace Barotrauma
}
for (int i = 1; i <= particleAmount; i++)
{
var worldRect = section.WorldRect;
Vector2 particlePos = new Vector2(
Rand.Range(section.rect.X, section.rect.Right),
Rand.Range(section.rect.Y - section.rect.Height, section.rect.Y));
Rand.Range(worldRect.X, worldRect.Right),
Rand.Range(worldRect.Y - worldRect.Height, worldRect.Y));
if (Submarine != null)
{
particlePos += Submarine.DrawPosition;
}
var particle = GameMain.ParticleManager.CreateParticle("shrapnel", particlePos, Rand.Vector(Rand.Range(1.0f, 50.0f)));
var particle = GameMain.ParticleManager.CreateParticle("shrapnel", particlePos, Rand.Vector(Rand.Range(1.0f, 50.0f)), collisionIgnoreTimer: 1f);
if (particle == null) break;
}
}
@@ -9,6 +9,8 @@ namespace Barotrauma
public Color? Color;
public string Metadata;
public float Alpha = 1.0f;
private const char definitionIndicator = '‖';
private const char attributeSeparator = ';';
private const char keyValueSeparator = ':';