Merge branch 'master' of https://github.com/Regalis11/Barotrauma
This commit is contained in:
@@ -521,8 +521,5 @@ namespace Barotrauma
|
||||
|
||||
protected virtual void OnStateChanged(AIState from, AIState to) { }
|
||||
protected virtual void OnTargetChanged(AITarget previousTarget, AITarget newTarget) { }
|
||||
|
||||
public virtual void ClientRead(IReadMessage msg) { }
|
||||
public virtual void ServerWrite(IWriteMessage msg) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4055,18 +4055,6 @@ namespace Barotrauma
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void ServerWrite(IWriteMessage msg)
|
||||
{
|
||||
msg.WriteByte((byte)State);
|
||||
PetBehavior?.ServerWrite(msg);
|
||||
}
|
||||
|
||||
public override void ClientRead(IReadMessage msg)
|
||||
{
|
||||
State = (AIState)msg.ReadByte();
|
||||
PetBehavior?.ClientRead(msg);
|
||||
}
|
||||
}
|
||||
|
||||
//the "memory" of the Character
|
||||
|
||||
+2
-1
@@ -200,7 +200,8 @@ namespace Barotrauma
|
||||
Leak.linkedTo.Any(e => e is Hull h && (character.CurrentHull == h || h.linkedTo.Contains(character.CurrentHull))),
|
||||
endNodeFilter = IsSuitableEndNode,
|
||||
// The Go To objective can be abandoned if the leak is fixed (in which case we don't want to use the dialogue)
|
||||
SpeakCannotReachCondition = () => !CheckObjectiveSpecific()
|
||||
// Only report about contextual targets.
|
||||
SpeakCannotReachCondition = () => isPriority && !CheckObjectiveSpecific()
|
||||
},
|
||||
onAbandon: () =>
|
||||
{
|
||||
|
||||
+18
-11
@@ -223,23 +223,30 @@ namespace Barotrauma
|
||||
Hull targetHull = GetTargetHull();
|
||||
if (!IsFollowOrder)
|
||||
{
|
||||
// Abandon if going through unsafe paths or targeting unsafe hulls.
|
||||
bool isUnreachable = HumanAIController.UnreachableHulls.Contains(targetHull);
|
||||
if (!objectiveManager.CurrentObjective.IgnoreUnsafeHulls)
|
||||
{
|
||||
if (HumanAIController.UnsafeHulls.Contains(targetHull))
|
||||
// Wait orders check this so that the bot temporarily leaves the unsafe hull.
|
||||
// Non-orders (that are not set to ignore the unsafe hulls) abandon. In practice this means e.g. repair and clean up item subobjectives (of the looping parent objective).
|
||||
// Other orders are only abandoned if the hull is unreachable, because the path is invalid or not found at all.
|
||||
if (IsWaitOrder || !objectiveManager.HasOrders())
|
||||
{
|
||||
isUnreachable = true;
|
||||
HumanAIController.AskToRecalculateHullSafety(targetHull);
|
||||
}
|
||||
else if (PathSteering?.CurrentPath != null)
|
||||
{
|
||||
foreach (WayPoint wp in PathSteering.CurrentPath.Nodes)
|
||||
if (HumanAIController.UnsafeHulls.Contains(targetHull))
|
||||
{
|
||||
if (wp.CurrentHull == null) { continue; }
|
||||
if (HumanAIController.UnsafeHulls.Contains(wp.CurrentHull))
|
||||
isUnreachable = true;
|
||||
HumanAIController.AskToRecalculateHullSafety(targetHull);
|
||||
}
|
||||
else if (PathSteering?.CurrentPath != null)
|
||||
{
|
||||
foreach (WayPoint wp in PathSteering.CurrentPath.Nodes)
|
||||
{
|
||||
isUnreachable = true;
|
||||
HumanAIController.AskToRecalculateHullSafety(wp.CurrentHull);
|
||||
if (wp.CurrentHull == null) { continue; }
|
||||
if (HumanAIController.UnsafeHulls.Contains(wp.CurrentHull))
|
||||
{
|
||||
isUnreachable = true;
|
||||
HumanAIController.AskToRecalculateHullSafety(wp.CurrentHull);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -222,7 +222,8 @@ namespace Barotrauma
|
||||
{
|
||||
var objective = new AIObjectiveGoTo(Item, character, objectiveManager)
|
||||
{
|
||||
TargetName = Item.Name
|
||||
TargetName = Item.Name,
|
||||
SpeakCannotReachCondition = () => isPriority
|
||||
};
|
||||
if (repairTool != null)
|
||||
{
|
||||
|
||||
+1
-1
@@ -287,7 +287,7 @@ namespace Barotrauma
|
||||
if (affliction.Prefab == null) { throw new Exception("Affliction prefab was null"); }
|
||||
float bestSuitability = 0.0f;
|
||||
Item bestItem = null;
|
||||
foreach (KeyValuePair<Identifier, float> treatmentSuitability in affliction.Prefab.TreatmentSuitability)
|
||||
foreach (KeyValuePair<Identifier, float> treatmentSuitability in affliction.Prefab.TreatmentSuitabilities)
|
||||
{
|
||||
if (currentTreatmentSuitabilities.ContainsKey(treatmentSuitability.Key) &&
|
||||
currentTreatmentSuitabilities[treatmentSuitability.Key] > bestSuitability)
|
||||
|
||||
+1
-1
@@ -109,6 +109,7 @@ namespace Barotrauma
|
||||
foreach (Affliction affliction in allAfflictions)
|
||||
{
|
||||
if (affliction.Prefab.IsBuff) { continue; }
|
||||
if (!affliction.Prefab.HasTreatments) { continue; }
|
||||
if (!ignoreTreatmentThreshold)
|
||||
{
|
||||
//other afflictions of the same type increase the "treatability"
|
||||
@@ -116,7 +117,6 @@ namespace Barotrauma
|
||||
float totalAfflictionStrength = character.CharacterHealth.GetTotalAdjustedAfflictionStrength(affliction);
|
||||
if (totalAfflictionStrength < affliction.Prefab.TreatmentThreshold) { continue; }
|
||||
}
|
||||
if (affliction.Prefab.TreatmentSuitability.None(kvp => kvp.Value > 0)) { continue; }
|
||||
if (allAfflictions.Any(otherAffliction => affliction.Prefab.IgnoreTreatmentIfAfflictedBy.Contains(otherAffliction.Identifier))) { continue; }
|
||||
yield return affliction;
|
||||
}
|
||||
|
||||
@@ -435,37 +435,34 @@ namespace Barotrauma
|
||||
spawnPoint ??= WayPoint.WayPointList.Where(wp => wp.SpawnType == SpawnType.Human && wp.Submarine?.Info.Type == SubmarineType.Player).GetRandomUnsynced();
|
||||
spawnPos = spawnPoint?.WorldPosition ?? Submarine.MainSub.WorldPosition;
|
||||
}
|
||||
var pet = Character.Create(speciesName, spawnPos, seed, spawnInitialItems: false);
|
||||
var petBehavior = (pet?.AIController as EnemyAIController)?.PetBehavior;
|
||||
if (petBehavior != null)
|
||||
|
||||
var characterPrefab = CharacterPrefab.FindBySpeciesName(speciesName.ToIdentifier());
|
||||
if (characterPrefab == null)
|
||||
{
|
||||
petBehavior.Owner = owner;
|
||||
var petBehaviorElement = subElement.Element("petbehavior");
|
||||
if (petBehaviorElement != null)
|
||||
DebugConsole.ThrowError($"Failed to load the pet \"{speciesName}\". Character prefab not found.");
|
||||
continue;
|
||||
}
|
||||
var pet = Character.Create(characterPrefab, spawnPos, seed, spawnInitialItems: false);
|
||||
if (pet != null)
|
||||
{
|
||||
var petBehavior = (pet.AIController as EnemyAIController)?.PetBehavior;
|
||||
if (petBehavior != null)
|
||||
{
|
||||
petBehavior.Hunger = petBehaviorElement.GetAttributeFloat("hunger", 50.0f);
|
||||
petBehavior.Happiness = petBehaviorElement.GetAttributeFloat("happiness", 50.0f);
|
||||
petBehavior.Owner = owner;
|
||||
var petBehaviorElement = subElement.Element("petbehavior");
|
||||
if (petBehaviorElement != null)
|
||||
{
|
||||
petBehavior.Hunger = petBehaviorElement.GetAttributeFloat("hunger", 50.0f);
|
||||
petBehavior.Happiness = petBehaviorElement.GetAttributeFloat("happiness", 50.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var inventoryElement = subElement.Element("inventory");
|
||||
if (inventoryElement != null)
|
||||
{
|
||||
pet.SpawnInventoryItems(pet.Inventory, inventoryElement.FromPackage(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ServerWrite(IWriteMessage msg)
|
||||
{
|
||||
msg.WriteRangedSingle(Happiness, 0.0f, MaxHappiness, 8);
|
||||
msg.WriteRangedSingle(Hunger, 0.0f, MaxHunger, 8);
|
||||
}
|
||||
|
||||
public void ClientRead(IReadMessage msg)
|
||||
{
|
||||
Happiness = msg.ReadRangedSingle(0.0f, MaxHappiness, 8);
|
||||
Hunger = msg.ReadRangedSingle(0.0f, MaxHunger, 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+37
-17
@@ -7,6 +7,7 @@ using System.Xml.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
using System.Collections.Immutable;
|
||||
using Barotrauma.Items.Components;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -841,20 +842,16 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
public readonly Sprite AfflictionOverlay;
|
||||
|
||||
public IEnumerable<KeyValuePair<Identifier, float>> TreatmentSuitability
|
||||
public ImmutableDictionary<Identifier, float> TreatmentSuitabilities
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var itemPrefab in ItemPrefab.Prefabs)
|
||||
{
|
||||
float suitability = itemPrefab.GetTreatmentSuitability(Identifier) + itemPrefab.GetTreatmentSuitability(AfflictionType);
|
||||
if (!MathUtils.NearlyEqual(suitability, 0.0f))
|
||||
{
|
||||
yield return new KeyValuePair<Identifier, float>(itemPrefab.Identifier, suitability);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
get;
|
||||
private set;
|
||||
} = new Dictionary<Identifier, float>().ToImmutableDictionary();
|
||||
|
||||
/// <summary>
|
||||
/// Can this affliction be treated with some item?
|
||||
/// </summary>
|
||||
public bool HasTreatments { get; private set; }
|
||||
|
||||
public AfflictionPrefab(ContentXElement element, AfflictionsFile file, Type type) : base(file, element.GetAttributeIdentifier("identifier", ""))
|
||||
{
|
||||
@@ -974,6 +971,22 @@ namespace Barotrauma
|
||||
constructor = type.GetConstructor(new[] { typeof(AfflictionPrefab), typeof(float) });
|
||||
}
|
||||
|
||||
private void RefreshTreatmentSuitabilities()
|
||||
{
|
||||
var newTreatmentSuitabilities = new Dictionary<Identifier, float>();
|
||||
|
||||
foreach (var itemPrefab in ItemPrefab.Prefabs)
|
||||
{
|
||||
float suitability = itemPrefab.GetTreatmentSuitability(Identifier) + itemPrefab.GetTreatmentSuitability(AfflictionType);
|
||||
if (!MathUtils.NearlyEqual(suitability, 0.0f))
|
||||
{
|
||||
newTreatmentSuitabilities.TryAdd(itemPrefab.Identifier, suitability);
|
||||
}
|
||||
}
|
||||
HasTreatments = newTreatmentSuitabilities.Any(kvp => kvp.Value > 0);
|
||||
TreatmentSuitabilities = newTreatmentSuitabilities.ToImmutableDictionary();
|
||||
}
|
||||
|
||||
public LocalizedString GetDescription(float strength, Description.TargetType targetType)
|
||||
{
|
||||
foreach (var description in Descriptions)
|
||||
@@ -993,9 +1006,16 @@ namespace Barotrauma
|
||||
return defaultDescription;
|
||||
}
|
||||
|
||||
public static void LoadAllEffects()
|
||||
/// <summary>
|
||||
/// Should be called before each round: loads all StatusEffects and refreshes treatment suitabilities.
|
||||
/// </summary>
|
||||
public static void LoadAllEffectsAndTreatmentSuitabilities()
|
||||
{
|
||||
Prefabs.ForEach(p => p.LoadEffects());
|
||||
foreach (var prefab in Prefabs)
|
||||
{
|
||||
prefab.RefreshTreatmentSuitabilities();
|
||||
prefab.LoadEffects();
|
||||
}
|
||||
}
|
||||
|
||||
public static void ClearAllEffects()
|
||||
@@ -1003,7 +1023,7 @@ namespace Barotrauma
|
||||
Prefabs.ForEach(p => p.ClearEffects());
|
||||
}
|
||||
|
||||
public void LoadEffects()
|
||||
private void LoadEffects()
|
||||
{
|
||||
ClearEffects();
|
||||
foreach (var subElement in configElement.Elements())
|
||||
@@ -1032,7 +1052,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearEffects()
|
||||
private void ClearEffects()
|
||||
{
|
||||
effects.Clear();
|
||||
periodicEffects.Clear();
|
||||
|
||||
@@ -1152,7 +1152,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<Identifier, float> treatment in affliction.Prefab.TreatmentSuitability)
|
||||
foreach (KeyValuePair<Identifier, float> treatment in affliction.Prefab.TreatmentSuitabilities)
|
||||
{
|
||||
float suitability = treatment.Value * strength;
|
||||
if (treatment.Value > strength)
|
||||
|
||||
@@ -392,7 +392,7 @@ namespace Barotrauma
|
||||
DateTime startTime = DateTime.Now;
|
||||
#endif
|
||||
RoundDuration = 0.0f;
|
||||
AfflictionPrefab.LoadAllEffects();
|
||||
AfflictionPrefab.LoadAllEffectsAndTreatmentSuitabilities();
|
||||
|
||||
MirrorLevel = mirrorLevel;
|
||||
if (SubmarineInfo == null)
|
||||
|
||||
@@ -135,7 +135,7 @@ namespace Barotrauma.Items.Components
|
||||
private void CreateTriggerBody()
|
||||
{
|
||||
System.Diagnostics.Debug.Assert(trigger == null, "LevelResource trigger already created!");
|
||||
var body = item.body ?? holdable.Body;
|
||||
var body = item.body ?? holdable?.Body;
|
||||
if (body != null && Attached)
|
||||
{
|
||||
trigger = new PhysicsBody(body.Width, body.Height, body.Radius,
|
||||
|
||||
@@ -178,7 +178,7 @@ namespace Barotrauma
|
||||
if (eventSet is null) { continue; }
|
||||
int count = childElement.GetAttributeInt("count", 0);
|
||||
if (count < 1) { continue; }
|
||||
FinishedEvents.Add(eventSet, count);
|
||||
FinishedEvents.TryAdd(eventSet, count);
|
||||
}
|
||||
|
||||
static EventSet FindSetRecursive(EventSet parentSet, Identifier setIdentifier)
|
||||
@@ -365,7 +365,7 @@ namespace Barotrauma
|
||||
if (FinishedEvents.Any())
|
||||
{
|
||||
var finishedEventsElement = new XElement(nameof(FinishedEvents));
|
||||
foreach (var (set, count) in FinishedEvents)
|
||||
foreach (var (set, count) in FinishedEvents.DistinctBy(f => f.Key.Identifier))
|
||||
{
|
||||
var element = new XElement(nameof(FinishedEvents),
|
||||
new XAttribute("set", set.Identifier),
|
||||
|
||||
@@ -1353,44 +1353,38 @@ namespace Barotrauma
|
||||
|
||||
if (startWaypoint.WorldPosition.X > endWaypoint.WorldPosition.X)
|
||||
{
|
||||
var temp = startWaypoint;
|
||||
startWaypoint = endWaypoint;
|
||||
endWaypoint = temp;
|
||||
(endWaypoint, startWaypoint) = (startWaypoint, endWaypoint);
|
||||
}
|
||||
|
||||
if (hallwayLength > 100 && isHorizontal)
|
||||
{
|
||||
//if the hallway is longer than 100 pixels, generate some waypoints inside it
|
||||
//for vertical hallways this isn't necessarily, it's done as a part of the ladder generation in AlignLadders
|
||||
WayPoint prevWayPoint = startWaypoint;
|
||||
WayPoint firstWayPoint = null;
|
||||
for (float x = leftHull.Rect.Right + 50; x < rightHull.Rect.X - 50; x += 100.0f)
|
||||
{
|
||||
var newWayPoint = new WayPoint(new Vector2(x, hullBounds.Y + 110.0f), SpawnType.Path, sub);
|
||||
firstWayPoint ??= newWayPoint;
|
||||
prevWayPoint.linkedTo.Add(newWayPoint);
|
||||
newWayPoint.linkedTo.Add(prevWayPoint);
|
||||
prevWayPoint = newWayPoint;
|
||||
}
|
||||
if (firstWayPoint != null)
|
||||
{
|
||||
firstWayPoint.linkedTo.Add(startWaypoint);
|
||||
startWaypoint.linkedTo.Add(firstWayPoint);
|
||||
}
|
||||
if (prevWayPoint != null)
|
||||
{
|
||||
prevWayPoint.linkedTo.Add(endWaypoint);
|
||||
endWaypoint.linkedTo.Add(prevWayPoint);
|
||||
}
|
||||
}
|
||||
|
||||
WayPoint closestWaypoint = null;
|
||||
float closestDistSqr = 30.0f * 30.0f;
|
||||
foreach (WayPoint waypoint in WayPoint.WayPointList)
|
||||
else
|
||||
{
|
||||
if (waypoint == startWaypoint) { continue; }
|
||||
float dist = Vector2.DistanceSquared(waypoint.WorldPosition, startWaypoint.WorldPosition);
|
||||
if (dist < closestDistSqr)
|
||||
{
|
||||
closestWaypoint = waypoint;
|
||||
closestDistSqr = dist;
|
||||
}
|
||||
}
|
||||
if (closestWaypoint != null)
|
||||
{
|
||||
startWaypoint.linkedTo.Add(closestWaypoint);
|
||||
closestWaypoint.linkedTo.Add(startWaypoint);
|
||||
startWaypoint.linkedTo.Add(endWaypoint);
|
||||
endWaypoint.linkedTo.Add(startWaypoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1444,7 +1438,7 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (MapEntity me in entities[module])
|
||||
{
|
||||
if (!(me is Gap gap)) { continue; }
|
||||
if (me is not Gap gap) { continue; }
|
||||
var door = gap.ConnectedDoor;
|
||||
if (door != null && !door.UseBetweenOutpostModules) { continue; }
|
||||
if (placedModules.Any(m => m.PreviousGap == gap || m.ThisGap == gap))
|
||||
@@ -1524,15 +1518,38 @@ namespace Barotrauma
|
||||
|
||||
static void RemoveLinkedEntity(MapEntity linked)
|
||||
{
|
||||
if (linked is Item linkedItem && linkedItem.Connections != null)
|
||||
if (linked is Item linkedItem)
|
||||
{
|
||||
foreach (Connection connection in linkedItem.Connections)
|
||||
if (linkedItem.Connections != null)
|
||||
{
|
||||
foreach (Wire w in connection.Wires.ToArray())
|
||||
foreach (Connection connection in linkedItem.Connections)
|
||||
{
|
||||
w?.Item.Remove();
|
||||
foreach (Wire w in connection.Wires.ToArray())
|
||||
{
|
||||
w?.Item.Remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
//if we end up removing a ladder, remove its waypoints too
|
||||
if (linkedItem.GetComponent<Ladder>() is Ladder ladder)
|
||||
{
|
||||
var ladderWaypoints = WayPoint.WayPointList.FindAll(wp => wp.Ladders == ladder);
|
||||
foreach (var ladderWaypoint in ladderWaypoints)
|
||||
{
|
||||
//got through all waypoints linked to the ladder waypoints, and link them together
|
||||
//so we don't end up breaking up any paths by removing the ladder waypoints
|
||||
for (int i = 0; i < ladderWaypoint.linkedTo.Count; i++)
|
||||
{
|
||||
if (ladderWaypoint.linkedTo[i] is not WayPoint waypoint1 || waypoint1.Ladders == ladder) { continue; }
|
||||
for (int j = i + 1; j < ladderWaypoint.linkedTo.Count; j++)
|
||||
{
|
||||
if (ladderWaypoint.linkedTo[j] is not WayPoint waypoint2 || waypoint2.Ladders == ladder) { continue; }
|
||||
waypoint1.ConnectTo(waypoint2);
|
||||
}
|
||||
}
|
||||
}
|
||||
ladderWaypoints.ForEach(wp => wp.Remove());
|
||||
}
|
||||
}
|
||||
linked.Remove();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user