(546717195) Use the AIObjectiveFightIntruders.IsValidTarget for deciding whether or not the button should flash.
This commit is contained in:
@@ -121,90 +121,7 @@ namespace Barotrauma
|
|||||||
MainLimb.PullJointWorldAnchorB = Collider.SimPosition;
|
MainLimb.PullJointWorldAnchorB = Collider.SimPosition;
|
||||||
MainLimb.PullJointEnabled = true;
|
MainLimb.PullJointEnabled = true;
|
||||||
}
|
}
|
||||||
character.SelectedConstruction = character.MemState[0].SelectedItem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (character.MemState[0].Animation == AnimController.Animation.CPR)
|
|
||||||
{
|
|
||||||
character.AnimController.Anim = AnimController.Animation.CPR;
|
|
||||||
}
|
|
||||||
else if (character.AnimController.Anim == AnimController.Animation.CPR)
|
|
||||||
{
|
|
||||||
character.AnimController.Anim = AnimController.Animation.None;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 newVelocity = Collider.LinearVelocity;
|
|
||||||
Vector2 newPosition = Collider.SimPosition;
|
|
||||||
float newRotation = Collider.Rotation;
|
|
||||||
float newAngularVelocity = Collider.AngularVelocity;
|
|
||||||
Collider.CorrectPosition(character.MemState, out newPosition, out newVelocity, out newRotation, out newAngularVelocity);
|
|
||||||
|
|
||||||
newVelocity = newVelocity.ClampLength(100.0f);
|
|
||||||
if (!MathUtils.IsValid(newVelocity)) { newVelocity = Vector2.Zero; }
|
|
||||||
overrideTargetMovement = newVelocity.LengthSquared() > 0.01f ? newVelocity : Vector2.Zero;
|
|
||||||
|
|
||||||
Collider.LinearVelocity = newVelocity;
|
|
||||||
Collider.AngularVelocity = newAngularVelocity;
|
|
||||||
|
|
||||||
float distSqrd = Vector2.DistanceSquared(newPosition, Collider.SimPosition);
|
|
||||||
float errorTolerance = character.AllowInput ? 0.01f : 0.2f;
|
|
||||||
if (distSqrd > errorTolerance)
|
|
||||||
{
|
|
||||||
if (distSqrd > 10.0f || !character.AllowInput)
|
|
||||||
{
|
|
||||||
Collider.TargetRotation = newRotation;
|
|
||||||
SetPosition(newPosition, lerp: distSqrd < 5.0f, ignorePlatforms: false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Collider.TargetRotation = newRotation;
|
|
||||||
Collider.TargetPosition = newPosition;
|
|
||||||
Collider.MoveToTargetPosition(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//unconscious/dead characters can't correct their position using AnimController movement
|
|
||||||
// -> we need to correct it manually
|
|
||||||
if (!character.AllowInput)
|
|
||||||
{
|
|
||||||
float mainLimbDistSqrd = Vector2.DistanceSquared(MainLimb.PullJointWorldAnchorA, Collider.SimPosition);
|
|
||||||
float mainLimbErrorTolerance = 0.1f;
|
|
||||||
//if the main limb is roughly at the correct position and the collider isn't moving (much at least),
|
|
||||||
//don't attempt to correct the position.
|
|
||||||
if (mainLimbDistSqrd > mainLimbErrorTolerance || Collider.LinearVelocity.LengthSquared() > 0.05f)
|
|
||||||
{
|
|
||||||
MainLimb.PullJointWorldAnchorB = Collider.SimPosition;
|
|
||||||
MainLimb.PullJointEnabled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
character.MemLocalState.Clear();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//remove states with a timestamp (there may still timestamp-based states
|
|
||||||
//in the list if the controlled character switches from timestamp-based interpolation to ID-based)
|
|
||||||
character.MemState.RemoveAll(m => m.Timestamp > 0.0f);
|
|
||||||
|
|
||||||
for (int i = 0; i < character.MemLocalState.Count; i++)
|
|
||||||
{
|
|
||||||
if (character.Submarine == null)
|
|
||||||
{
|
|
||||||
//transform in-sub coordinates to outside coordinates
|
|
||||||
if (character.MemLocalState[i].Position.Y > lowestSubPos)
|
|
||||||
{
|
|
||||||
character.MemLocalState[i].TransformInToOutside();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (currentHull?.Submarine != null)
|
|
||||||
{
|
|
||||||
//transform outside coordinates to in-sub coordinates
|
|
||||||
if (character.MemLocalState[i].Position.Y < lowestSubPos)
|
|
||||||
{
|
|
||||||
character.MemLocalState[i].TransformOutToInside(currentHull.Submarine);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
character.MemLocalState.Clear();
|
character.MemLocalState.Clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1450,10 +1450,7 @@ namespace Barotrauma
|
|||||||
bool hasLeaks = Character.Controlled.CurrentHull.ConnectedGaps.Any(g => !g.IsRoomToRoom && g.Open > 0.0f);
|
bool hasLeaks = Character.Controlled.CurrentHull.ConnectedGaps.Any(g => !g.IsRoomToRoom && g.Open > 0.0f);
|
||||||
ToggleReportButton("reportbreach", hasLeaks);
|
ToggleReportButton("reportbreach", hasLeaks);
|
||||||
|
|
||||||
bool hasIntruders = Character.CharacterList.Any(c =>
|
bool hasIntruders = Character.CharacterList.Any(c => c.CurrentHull == Character.Controlled.CurrentHull && AIObjectiveFightIntruders.IsValidTarget(Character.Controlled, c));
|
||||||
c.CurrentHull == Character.Controlled.CurrentHull && !c.IsDead &&
|
|
||||||
(c.AIController is EnemyAIController || (c.TeamID != Character.Controlled.TeamID && c.TeamID != Character.TeamType.FriendlyNPC)));
|
|
||||||
|
|
||||||
ToggleReportButton("reportintruders", hasIntruders);
|
ToggleReportButton("reportintruders", hasIntruders);
|
||||||
|
|
||||||
foreach (GUIComponent reportButton in reportButtonFrame.Children)
|
foreach (GUIComponent reportButton in reportButtonFrame.Children)
|
||||||
|
|||||||
@@ -730,6 +730,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private GUILayoutGroup subPreviewContainer;
|
private GUILayoutGroup subPreviewContainer;
|
||||||
|
|
||||||
|
private GUILayoutGroup subPreviewContainer;
|
||||||
|
|
||||||
private GUIButton loadGameButton;
|
private GUIButton loadGameButton;
|
||||||
|
|
||||||
public Action<Submarine, string, string> StartNewGame;
|
public Action<Submarine, string, string> StartNewGame;
|
||||||
|
|||||||
@@ -15,14 +15,14 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private float sortTimer;
|
private float sortTimer;
|
||||||
private float crouchRaycastTimer;
|
private float crouchRaycastTimer;
|
||||||
private float reportTimer;
|
private float reactTimer;
|
||||||
private float hullVisibilityTimer;
|
private float hullVisibilityTimer;
|
||||||
private bool shouldCrouch;
|
private bool shouldCrouch;
|
||||||
|
|
||||||
|
const float reactionTime = 0.5f;
|
||||||
|
const float hullVisibilityInterval = 0.5f;
|
||||||
const float crouchRaycastInterval = 1;
|
const float crouchRaycastInterval = 1;
|
||||||
const float reportInterval = 1;
|
|
||||||
const float sortObjectiveInterval = 1;
|
const float sortObjectiveInterval = 1;
|
||||||
const float hullVisibilityInterval = 1;
|
|
||||||
|
|
||||||
public static float HULL_SAFETY_THRESHOLD = 50;
|
public static float HULL_SAFETY_THRESHOLD = 50;
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ namespace Barotrauma
|
|||||||
insideSteering = new IndoorsSteeringManager(this, true, false);
|
insideSteering = new IndoorsSteeringManager(this, true, false);
|
||||||
outsideSteering = new SteeringManager(this);
|
outsideSteering = new SteeringManager(this);
|
||||||
objectiveManager = new AIObjectiveManager(c);
|
objectiveManager = new AIObjectiveManager(c);
|
||||||
reportTimer = Rand.Range(0f, reportInterval);
|
reactTimer = Rand.Range(0f, reactionTime);
|
||||||
sortTimer = Rand.Range(0f, sortObjectiveInterval);
|
sortTimer = Rand.Range(0f, sortObjectiveInterval);
|
||||||
hullVisibilityTimer = Rand.Range(0f, hullVisibilityTimer);
|
hullVisibilityTimer = Rand.Range(0f, hullVisibilityTimer);
|
||||||
InitProjSpecific();
|
InitProjSpecific();
|
||||||
@@ -118,23 +118,22 @@ namespace Barotrauma
|
|||||||
objectiveManager.SortObjectives();
|
objectiveManager.SortObjectives();
|
||||||
sortTimer = sortObjectiveInterval;
|
sortTimer = sortObjectiveInterval;
|
||||||
}
|
}
|
||||||
|
if (reactTimer > 0.0f)
|
||||||
if (reportTimer > 0.0f)
|
|
||||||
{
|
{
|
||||||
reportTimer -= deltaTime;
|
reactTimer -= deltaTime;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Character.CurrentHull != null)
|
if (Character.CurrentHull != null)
|
||||||
{
|
{
|
||||||
VisibleHulls.ForEach(h => PropagateHullSafety(Character.Controlled, h));
|
VisibleHulls.ForEach(h => PropagateHullSafety(Character, h));
|
||||||
}
|
}
|
||||||
if (Character.SpeechImpediment < 100.0f)
|
if (Character.SpeechImpediment < 100.0f)
|
||||||
{
|
{
|
||||||
ReportProblems();
|
ReportProblems();
|
||||||
UpdateSpeaking();
|
UpdateSpeaking();
|
||||||
}
|
}
|
||||||
reportTimer = reportInterval;
|
reactTimer = reactionTime * Rand.Range(0.75f, 1.25f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (objectiveManager.CurrentObjective == null) { return; }
|
if (objectiveManager.CurrentObjective == null) { return; }
|
||||||
@@ -374,14 +373,38 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
foreach (var hull in VisibleHulls)
|
foreach (var hull in VisibleHulls)
|
||||||
{
|
{
|
||||||
|
foreach (Character c in Character.CharacterList)
|
||||||
|
{
|
||||||
|
if (c.CurrentHull != hull) { continue; }
|
||||||
|
if (AIObjectiveFightIntruders.IsValidTarget(c, Character))
|
||||||
|
{
|
||||||
|
AddTargets<AIObjectiveFightIntruders, Character>(Character, c);
|
||||||
|
if (newOrder == null)
|
||||||
|
{
|
||||||
|
var orderPrefab = Order.PrefabList.Find(o => o.AITag == "reportintruders");
|
||||||
|
newOrder = new Order(orderPrefab, c.CurrentHull, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (AIObjectiveExtinguishFires.IsValidTarget(hull, Character))
|
if (AIObjectiveExtinguishFires.IsValidTarget(hull, Character))
|
||||||
{
|
{
|
||||||
if (AddTargets<AIObjectiveExtinguishFires, Hull>(Character, hull))
|
AddTargets<AIObjectiveExtinguishFires, Hull>(Character, hull);
|
||||||
|
if (newOrder == null)
|
||||||
{
|
{
|
||||||
if (hull == Character.CurrentHull)
|
var orderPrefab = Order.PrefabList.Find(o => o.AITag == "reportfire");
|
||||||
|
newOrder = new Order(orderPrefab, hull, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (Character c in Character.CharacterList)
|
||||||
|
{
|
||||||
|
if (c.CurrentHull != hull) { continue; }
|
||||||
|
if (AIObjectiveRescueAll.IsValidTarget(c, Character))
|
||||||
|
{
|
||||||
|
AddTargets<AIObjectiveRescueAll, Character>(c, Character);
|
||||||
|
if (newOrder == null)
|
||||||
{
|
{
|
||||||
var orderPrefab = Order.PrefabList.Find(o => o.AITag == "reportfire");
|
var orderPrefab = Order.PrefabList.Find(o => o.AITag == "requestfirstaid");
|
||||||
newOrder = new Order(orderPrefab, Character.CurrentHull, null);
|
newOrder = new Order(orderPrefab, c.CurrentHull, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -389,13 +412,11 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (AIObjectiveFixLeaks.IsValidTarget(gap, Character))
|
if (AIObjectiveFixLeaks.IsValidTarget(gap, Character))
|
||||||
{
|
{
|
||||||
if (AddTargets<AIObjectiveFixLeaks, Gap>(Character, gap))
|
AddTargets<AIObjectiveFixLeaks, Gap>(Character, gap);
|
||||||
|
if (newOrder == null)
|
||||||
{
|
{
|
||||||
if (hull == Character.CurrentHull)
|
var orderPrefab = Order.PrefabList.Find(o => o.AITag == "reportbreach");
|
||||||
{
|
newOrder = new Order(orderPrefab, hull, null);
|
||||||
var orderPrefab = Order.PrefabList.Find(o => o.AITag == "reportbreach");
|
|
||||||
newOrder = new Order(orderPrefab, Character.CurrentHull, null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -405,39 +426,14 @@ namespace Barotrauma
|
|||||||
if (AIObjectiveRepairItems.IsValidTarget(item, Character))
|
if (AIObjectiveRepairItems.IsValidTarget(item, Character))
|
||||||
{
|
{
|
||||||
if (item.Repairables.All(r => item.Condition > r.ShowRepairUIThreshold)) { continue; }
|
if (item.Repairables.All(r => item.Condition > r.ShowRepairUIThreshold)) { continue; }
|
||||||
if (AddTargets<AIObjectiveRepairItems, Item>(Character, item))
|
AddTargets<AIObjectiveRepairItems, Item>(Character, item);
|
||||||
|
if (newOrder == null)
|
||||||
{
|
{
|
||||||
if (hull == Character.CurrentHull)
|
var orderPrefab = Order.PrefabList.Find(o => o.AITag == "reportbrokendevices");
|
||||||
{
|
newOrder = new Order(orderPrefab, item.CurrentHull, item.Repairables?.FirstOrDefault());
|
||||||
var orderPrefab = Order.PrefabList.Find(o => o.AITag == "reportbrokendevices");
|
|
||||||
newOrder = new Order(orderPrefab, Character.CurrentHull, item.Repairables?.FirstOrDefault());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (Character c in Character.CharacterList)
|
|
||||||
{
|
|
||||||
if (c.CurrentHull != hull) { continue; }
|
|
||||||
if (AIObjectiveFightIntruders.IsValidTarget(c, Character))
|
|
||||||
{
|
|
||||||
if (AddTargets<AIObjectiveFightIntruders, Character>(Character, c))
|
|
||||||
{
|
|
||||||
if (hull == Character.CurrentHull)
|
|
||||||
{
|
|
||||||
var orderPrefab = Order.PrefabList.Find(o => o.AITag == "reportintruders");
|
|
||||||
newOrder = new Order(orderPrefab, Character.CurrentHull, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Character.Bleeding > 1.0f || Character.Vitality < Character.MaxVitality * 0.1f)
|
|
||||||
{
|
|
||||||
if (AddTargets<AIObjectiveRescueAll, Character>(Character, Character))
|
|
||||||
{
|
|
||||||
var orderPrefab = Order.PrefabList.Find(o => o.AITag == "requestfirstaid");
|
|
||||||
newOrder = new Order(orderPrefab, Character.CurrentHull, null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (newOrder != null)
|
if (newOrder != null)
|
||||||
@@ -646,6 +642,7 @@ namespace Barotrauma
|
|||||||
DoForEachCrewMember(character, (humanAi) => humanAi.RefreshHullSafety(hull));
|
DoForEachCrewMember(character, (humanAi) => humanAi.RefreshHullSafety(hull));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float CurrentHullSafety { get; private set; }
|
||||||
private void RefreshHullSafety(Hull hull)
|
private void RefreshHullSafety(Hull hull)
|
||||||
{
|
{
|
||||||
if (GetHullSafety(hull, Character, VisibleHulls) > HULL_SAFETY_THRESHOLD)
|
if (GetHullSafety(hull, Character, VisibleHulls) > HULL_SAFETY_THRESHOLD)
|
||||||
@@ -740,12 +737,34 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public float GetHullSafety(Hull hull, Character character, IEnumerable<Hull> visibleHulls = null)
|
public float GetHullSafety(Hull hull, Character character, IEnumerable<Hull> visibleHulls = null)
|
||||||
{
|
{
|
||||||
if (hull == null) { return 0; }
|
bool updateCurrentHullSafety = character == Character && character.CurrentHull == hull;
|
||||||
|
if (hull == null)
|
||||||
|
{
|
||||||
|
if (updateCurrentHullSafety)
|
||||||
|
{
|
||||||
|
CurrentHullSafety = 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (character == Character)
|
||||||
|
{
|
||||||
|
// If the character is this character, we can use the cached hulls.
|
||||||
|
// If no visible hulls are provided, the calculations don't take visible/adjacent hulls into account.
|
||||||
|
if (visibleHulls == null)
|
||||||
|
{
|
||||||
|
visibleHulls = VisibleHulls;
|
||||||
|
}
|
||||||
|
}
|
||||||
bool ignoreFire = ObjectiveManager.IsCurrentObjective<AIObjectiveExtinguishFires>() || ObjectiveManager.IsCurrentObjective<AIObjectiveExtinguishFire>();
|
bool ignoreFire = ObjectiveManager.IsCurrentObjective<AIObjectiveExtinguishFires>() || ObjectiveManager.IsCurrentObjective<AIObjectiveExtinguishFire>();
|
||||||
bool ignoreWater = HasDivingSuit(character);
|
bool ignoreWater = HasDivingSuit(character);
|
||||||
bool ignoreOxygen = ignoreWater || HasDivingMask(character);
|
bool ignoreOxygen = ignoreWater || HasDivingMask(character);
|
||||||
bool ignoreEnemies = ObjectiveManager.IsCurrentObjective<AIObjectiveFightIntruders>();
|
bool ignoreEnemies = ObjectiveManager.IsCurrentObjective<AIObjectiveFightIntruders>();
|
||||||
return GetHullSafety(hull, visibleHulls, character, ignoreWater, ignoreOxygen, ignoreFire, ignoreEnemies);
|
float safety = GetHullSafety(hull, visibleHulls, character, ignoreWater, ignoreOxygen, ignoreFire, ignoreEnemies);
|
||||||
|
if (updateCurrentHullSafety)
|
||||||
|
{
|
||||||
|
CurrentHullSafety = safety;
|
||||||
|
}
|
||||||
|
return safety;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float GetHullSafety(Hull hull, IEnumerable<Hull> visibleHulls, Character character, bool ignoreWater = false, bool ignoreOxygen = false, bool ignoreFire = false, bool ignoreEnemies = false)
|
public static float GetHullSafety(Hull hull, IEnumerable<Hull> visibleHulls, Character character, bool ignoreWater = false, bool ignoreOxygen = false, bool ignoreFire = false, bool ignoreEnemies = false)
|
||||||
|
|||||||
+11
-7
@@ -12,7 +12,7 @@ namespace Barotrauma
|
|||||||
public override bool ForceRun => true;
|
public override bool ForceRun => true;
|
||||||
|
|
||||||
// TODO: expose?
|
// TODO: expose?
|
||||||
const float priorityIncrease = 25;
|
const float priorityIncrease = 100;
|
||||||
const float priorityDecrease = 10;
|
const float priorityDecrease = 10;
|
||||||
const float SearchHullInterval = 3.0f;
|
const float SearchHullInterval = 3.0f;
|
||||||
const float clearUnreachableInterval = 30;
|
const float clearUnreachableInterval = 30;
|
||||||
@@ -51,8 +51,7 @@ namespace Barotrauma
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (character.OxygenAvailable < CharacterHealth.LowOxygenThreshold) { Priority = 100; }
|
if (character.OxygenAvailable < CharacterHealth.LowOxygenThreshold) { Priority = 100; }
|
||||||
// TODO: no need to update every frame?
|
currenthullSafety = HumanAIController.CurrentHullSafety;
|
||||||
currenthullSafety = HumanAIController.GetCurrentHullSafety();
|
|
||||||
if (currenthullSafety > HumanAIController.HULL_SAFETY_THRESHOLD)
|
if (currenthullSafety > HumanAIController.HULL_SAFETY_THRESHOLD)
|
||||||
{
|
{
|
||||||
Priority -= priorityDecrease * deltaTime;
|
Priority -= priorityDecrease * deltaTime;
|
||||||
@@ -65,6 +64,7 @@ namespace Barotrauma
|
|||||||
Priority = MathHelper.Clamp(Priority, 0, 100);
|
Priority = MathHelper.Clamp(Priority, 0, 100);
|
||||||
if (divingGearObjective != null && !divingGearObjective.IsCompleted() && divingGearObjective.CanBeCompleted)
|
if (divingGearObjective != null && !divingGearObjective.IsCompleted() && divingGearObjective.CanBeCompleted)
|
||||||
{
|
{
|
||||||
|
// Boost the priority while seeking the diving gear
|
||||||
Priority = Math.Max(Priority, Math.Min(AIObjectiveManager.OrderPriority + 20, 100));
|
Priority = Math.Max(Priority, Math.Min(AIObjectiveManager.OrderPriority + 20, 100));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,6 +123,10 @@ namespace Barotrauma
|
|||||||
},
|
},
|
||||||
onAbandon: () => unreachable.Add(goToObjective.Target as Hull));
|
onAbandon: () => unreachable.Add(goToObjective.Target as Hull));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
goToObjective = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (goToObjective != null) { return; }
|
if (goToObjective != null) { return; }
|
||||||
if (currentHull == null) { return; }
|
if (currentHull == null) { return; }
|
||||||
@@ -148,8 +152,8 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
if (escapeVel != Vector2.Zero)
|
if (escapeVel != Vector2.Zero)
|
||||||
{
|
{
|
||||||
float left = HumanAIController.VisibleHulls.Min(h => h.Rect.X) + 50;
|
float left = currentHull.Rect.X + 50;
|
||||||
float right = HumanAIController.VisibleHulls.Max(h => h.Rect.Right) - 50;
|
float right = currentHull.Rect.Right - 50;
|
||||||
//only move if we haven't reached the edge of the room
|
//only move if we haven't reached the edge of the room
|
||||||
if (escapeVel.X < 0 && character.Position.X > left || escapeVel.X > 0 && character.Position.X < right)
|
if (escapeVel.X < 0 && character.Position.X > left || escapeVel.X > 0 && character.Position.X < right)
|
||||||
{
|
{
|
||||||
@@ -190,14 +194,14 @@ namespace Barotrauma
|
|||||||
//skip the hull if the safety is already less than the best hull
|
//skip the hull if the safety is already less than the best hull
|
||||||
//(no need to do the expensive pathfinding if we already know we're not going to choose this hull)
|
//(no need to do the expensive pathfinding if we already know we're not going to choose this hull)
|
||||||
if (hullSafety < bestValue) { continue; }
|
if (hullSafety < bestValue) { continue; }
|
||||||
// Each unsafe node reduces the hull safety value.
|
|
||||||
// Ignore current hull, because otherwise the would block all paths from the current hull to the target hull.
|
|
||||||
var path = PathSteering.PathFinder.FindPath(character.SimPosition, hull.SimPosition);
|
var path = PathSteering.PathFinder.FindPath(character.SimPosition, hull.SimPosition);
|
||||||
if (path.Unreachable)
|
if (path.Unreachable)
|
||||||
{
|
{
|
||||||
unreachable.Add(hull);
|
unreachable.Add(hull);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
// Each unsafe node reduces the hull safety value.
|
||||||
|
// Ignore the current hull, because otherwise we couldn't find a path out.
|
||||||
int unsafeNodes = path.Nodes.Count(n => n.CurrentHull != character.CurrentHull && HumanAIController.UnsafeHulls.Contains(n.CurrentHull));
|
int unsafeNodes = path.Nodes.Count(n => n.CurrentHull != character.CurrentHull && HumanAIController.UnsafeHulls.Contains(n.CurrentHull));
|
||||||
hullSafety /= 1 + unsafeNodes;
|
hullSafety /= 1 + unsafeNodes;
|
||||||
// If the target is not inside a friendly submarine, considerably reduce the hull safety.
|
// If the target is not inside a friendly submarine, considerably reduce the hull safety.
|
||||||
|
|||||||
@@ -543,6 +543,32 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
DebugConsole.ThrowError("AIObjectiveFixLeak failed - the item \"" + weldingTool + "\" has no RepairTool component but is tagged as a welding tool");
|
DebugConsole.ThrowError("AIObjectiveFixLeak failed - the item \"" + weldingTool + "\" has no RepairTool component but is tagged as a welding tool");
|
||||||
|
#endif
|
||||||
|
abandon = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Vector2 gapDiff = Leak.WorldPosition - character.WorldPosition;
|
||||||
|
// TODO: use the collider size/reach?
|
||||||
|
if (!character.AnimController.InWater && Math.Abs(gapDiff.X) < 100 && gapDiff.Y < 0.0f && gapDiff.Y > -150)
|
||||||
|
{
|
||||||
|
HumanAIController.AnimController.Crouching = true;
|
||||||
|
}
|
||||||
|
float reach = ConvertUnits.ToSimUnits(repairTool.Range);
|
||||||
|
bool canOperate = ConvertUnits.ToSimUnits(gapDiff.Length()) < reach * 1.5f;
|
||||||
|
if (canOperate)
|
||||||
|
{
|
||||||
|
TryAddSubObjective(ref operateObjective, () => new AIObjectiveOperateItem(repairTool, character, objectiveManager, option: "", requireEquip: true, operateTarget: Leak));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TryAddSubObjective(ref gotoObjective, () => new AIObjectiveGoTo(ConvertUnits.ToSimUnits(GetStandPosition()), character, objectiveManager) { CloseEnough = reach * 0.75f });
|
||||||
|
}
|
||||||
|
if (subObjectives.Any()) { return; }
|
||||||
|
var repairTool = weldingTool.GetComponent<RepairTool>();
|
||||||
|
if (repairTool == null)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
DebugConsole.ThrowError("AIObjectiveFixLeak failed - the item \"" + weldingTool + "\" has no RepairTool component but is tagged as a welding tool");
|
||||||
#endif
|
#endif
|
||||||
abandon = true;
|
abandon = true;
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -89,6 +89,21 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Update(float deltaTime)
|
||||||
|
{
|
||||||
|
if (objectiveManager.CurrentObjective == this)
|
||||||
|
{
|
||||||
|
if (randomTimer > 0)
|
||||||
|
{
|
||||||
|
randomTimer -= deltaTime;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetRandom();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override bool IsCompleted() => false;
|
public override bool IsCompleted() => false;
|
||||||
public override bool CanBeCompleted => true;
|
public override bool CanBeCompleted => true;
|
||||||
|
|
||||||
|
|||||||
@@ -18,10 +18,26 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private Character character;
|
private Character character;
|
||||||
|
|
||||||
|
|
||||||
|
private float _waitTimer;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When set above zero, the character will stand still doing nothing until the timer runs out. Does not affect orders.
|
/// When set above zero, the character will stand still doing nothing until the timer runs out. Does not affect orders, find safety or combat.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float WaitTimer;
|
public float WaitTimer
|
||||||
|
{
|
||||||
|
get { return _waitTimer; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (CurrentObjective is AIObjectiveCombat || CurrentObjective is AIObjectiveFindSafety)
|
||||||
|
{
|
||||||
|
_waitTimer = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_waitTimer = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public AIObjective CurrentOrder { get; private set; }
|
public AIObjective CurrentOrder { get; private set; }
|
||||||
public AIObjective CurrentObjective { get; private set; }
|
public AIObjective CurrentObjective { get; private set; }
|
||||||
@@ -197,6 +213,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Wait, if not swimming, climbing, or staying in a forbidden/unsafe hull.
|
||||||
if (character.AIController is HumanAIController humanAI && humanAI.SteeringManager != null)
|
if (character.AIController is HumanAIController humanAI && humanAI.SteeringManager != null)
|
||||||
{
|
{
|
||||||
if (!character.AnimController.InWater &&
|
if (!character.AnimController.InWater &&
|
||||||
|
|||||||
@@ -861,6 +861,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
isCompleted = true;
|
isCompleted = true;
|
||||||
}
|
}
|
||||||
|
if (component.AIOperate(deltaTime, character, this))
|
||||||
|
{
|
||||||
|
isCompleted = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -23,6 +23,12 @@ namespace Barotrauma
|
|||||||
public AIObjectiveRescue(Character character, Character targetCharacter, AIObjectiveManager objectiveManager, float priorityModifier = 1)
|
public AIObjectiveRescue(Character character, Character targetCharacter, AIObjectiveManager objectiveManager, float priorityModifier = 1)
|
||||||
: base(character, objectiveManager, priorityModifier)
|
: base(character, objectiveManager, priorityModifier)
|
||||||
{
|
{
|
||||||
|
if (targetCharacter != character)
|
||||||
|
{
|
||||||
|
// TODO: enable healing self too
|
||||||
|
abandon = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.targetCharacter = targetCharacter;
|
this.targetCharacter = targetCharacter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,7 +207,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public override bool IsCompleted()
|
public override bool IsCompleted()
|
||||||
{
|
{
|
||||||
bool isCompleted = targetCharacter.Vitality / targetCharacter.MaxVitality > AIObjectiveRescueAll.GetVitalityThreshold(objectiveManager);
|
bool isCompleted = targetCharacter.Bleeding <= 0 && targetCharacter.Vitality / targetCharacter.MaxVitality > AIObjectiveRescueAll.GetVitalityThreshold(objectiveManager);
|
||||||
if (isCompleted)
|
if (isCompleted)
|
||||||
{
|
{
|
||||||
character.Speak(TextManager.Get("DialogTargetHealed").Replace("[targetname]", targetCharacter.Name),
|
character.Speak(TextManager.Get("DialogTargetHealed").Replace("[targetname]", targetCharacter.Name),
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace Barotrauma
|
|||||||
public override string DebugTag => "rescue all";
|
public override string DebugTag => "rescue all";
|
||||||
public override bool ForceRun => true;
|
public override bool ForceRun => true;
|
||||||
|
|
||||||
private const float vitalityThreshold = 0.85f;
|
private const float vitalityThreshold = 0.8f;
|
||||||
private const float vitalityThresholdForOrders = 0.95f;
|
private const float vitalityThresholdForOrders = 0.95f;
|
||||||
public static float GetVitalityThreshold(AIObjectiveManager manager) => manager.CurrentOrder is AIObjectiveRescueAll ? vitalityThresholdForOrders : vitalityThreshold;
|
public static float GetVitalityThreshold(AIObjectiveManager manager) => manager.CurrentOrder is AIObjectiveRescueAll ? vitalityThresholdForOrders : vitalityThreshold;
|
||||||
|
|
||||||
@@ -35,10 +35,9 @@ namespace Barotrauma
|
|||||||
public static bool IsValidTarget(Character target, Character character)
|
public static bool IsValidTarget(Character target, Character character)
|
||||||
{
|
{
|
||||||
if (target == null || target.IsDead || target.Removed) { return false; }
|
if (target == null || target.IsDead || target.Removed) { return false; }
|
||||||
if (target == character) { return false; } // TODO: enable healing self
|
|
||||||
if (!HumanAIController.IsFriendly(character, target)) { return false; }
|
if (!HumanAIController.IsFriendly(character, target)) { return false; }
|
||||||
if (!(character.AIController is HumanAIController humanAI)) { return false; }
|
if (!(character.AIController is HumanAIController humanAI)) { return false; }
|
||||||
if (target.Vitality / target.MaxVitality > GetVitalityThreshold(humanAI.ObjectiveManager)) { return false; }
|
if (target.Bleeding < 1 && target.Vitality / target.MaxVitality > GetVitalityThreshold(humanAI.ObjectiveManager)) { return false; }
|
||||||
if (target.Submarine == null) { return false; }
|
if (target.Submarine == null) { return false; }
|
||||||
if (target.Submarine.TeamID != character.Submarine.TeamID) { return false; }
|
if (target.Submarine.TeamID != character.Submarine.TeamID) { return false; }
|
||||||
if (target.CurrentHull == null) { return false; }
|
if (target.CurrentHull == null) { return false; }
|
||||||
|
|||||||
@@ -1145,24 +1145,6 @@ namespace Barotrauma
|
|||||||
SmoothedCursorPosition = cursorPosition - smoothedCursorDiff;
|
SmoothedCursorPosition = cursorPosition - smoothedCursorDiff;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(this is AICharacter) || Controlled == this || IsRemotePlayer)
|
|
||||||
{
|
|
||||||
//apply some smoothing to the cursor positions of remote players when playing as a client
|
|
||||||
//to make aiming look a little less choppy
|
|
||||||
Vector2 smoothedCursorDiff = cursorPosition - SmoothedCursorPosition;
|
|
||||||
smoothedCursorDiff = NetConfig.InterpolateCursorPositionError(smoothedCursorDiff);
|
|
||||||
SmoothedCursorPosition = cursorPosition - smoothedCursorDiff;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(this is AICharacter) || Controlled == this || IsRemotePlayer)
|
|
||||||
{
|
|
||||||
//apply some smoothing to the cursor positions of remote players when playing as a client
|
|
||||||
//to make aiming look a little less choppy
|
|
||||||
Vector2 smoothedCursorDiff = cursorPosition - SmoothedCursorPosition;
|
|
||||||
smoothedCursorDiff = NetConfig.InterpolateCursorPositionError(smoothedCursorDiff);
|
|
||||||
SmoothedCursorPosition = cursorPosition - smoothedCursorDiff;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(this is AICharacter) || Controlled == this || IsRemotePlayer)
|
if (!(this is AICharacter) || Controlled == this || IsRemotePlayer)
|
||||||
{
|
{
|
||||||
if (speedMultipliers.Count == 0) return 1f;
|
if (speedMultipliers.Count == 0) return 1f;
|
||||||
|
|||||||
@@ -1000,6 +1000,25 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (targetItem.Prefab.DeconstructItems.Any())
|
||||||
|
{
|
||||||
|
inputContainer.Inventory.RemoveItem(targetItem);
|
||||||
|
Entity.Spawner.AddToRemoveQueue(targetItem);
|
||||||
|
MoveInputQueue();
|
||||||
|
PutItemsToLinkedContainer();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (outputContainer.Inventory.Items.All(i => i != null))
|
||||||
|
{
|
||||||
|
targetItem.Drop(dropper: null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outputContainer.Inventory.TryPutItem(targetItem, user: null, createNetworkEvent: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (targetItem.Prefab.DeconstructItems.Any())
|
if (targetItem.Prefab.DeconstructItems.Any())
|
||||||
{
|
{
|
||||||
inputContainer.Inventory.RemoveItem(targetItem);
|
inputContainer.Inventory.RemoveItem(targetItem);
|
||||||
|
|||||||
@@ -144,17 +144,6 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector2 SteeringInput
|
|
||||||
{
|
|
||||||
get { return steeringInput; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (!MathUtils.IsValid(value)) return;
|
|
||||||
steeringInput.X = MathHelper.Clamp(value.X, -100.0f, 100.0f);
|
|
||||||
steeringInput.Y = MathHelper.Clamp(value.Y, -100.0f, 100.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public SteeringPath SteeringPath
|
public SteeringPath SteeringPath
|
||||||
{
|
{
|
||||||
if (!CanBeSelected) return false;
|
if (!CanBeSelected) return false;
|
||||||
@@ -175,6 +164,12 @@ namespace Barotrauma.Items.Components
|
|||||||
set { posToMaintain = value; }
|
set { posToMaintain = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vector2? PosToMaintain
|
||||||
|
{
|
||||||
|
get { return posToMaintain; }
|
||||||
|
set { posToMaintain = value; }
|
||||||
|
}
|
||||||
|
|
||||||
struct ObstacleDebugInfo
|
struct ObstacleDebugInfo
|
||||||
{
|
{
|
||||||
public Vector2 Point1;
|
public Vector2 Point1;
|
||||||
|
|||||||
@@ -1171,70 +1171,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateTransform()
|
|
||||||
{
|
|
||||||
Submarine prevSub = Submarine;
|
|
||||||
|
|
||||||
FindHull();
|
|
||||||
|
|
||||||
if (Submarine == null && prevSub != null)
|
|
||||||
{
|
|
||||||
body.SetTransform(body.SimPosition + prevSub.SimPosition, body.Rotation);
|
|
||||||
}
|
|
||||||
else if (Submarine != null && prevSub == null)
|
|
||||||
{
|
|
||||||
body.SetTransform(body.SimPosition - Submarine.SimPosition, body.Rotation);
|
|
||||||
}
|
|
||||||
else if (Submarine != null && prevSub != null && Submarine != prevSub)
|
|
||||||
{
|
|
||||||
body.SetTransform(body.SimPosition + prevSub.SimPosition - Submarine.SimPosition, body.Rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 displayPos = ConvertUnits.ToDisplayUnits(body.SimPosition);
|
|
||||||
rect.X = (int)(displayPos.X - rect.Width / 2.0f);
|
|
||||||
rect.Y = (int)(displayPos.Y + rect.Height / 2.0f);
|
|
||||||
|
|
||||||
if (Math.Abs(body.LinearVelocity.X) > NetConfig.MaxPhysicsBodyVelocity ||
|
|
||||||
Math.Abs(body.LinearVelocity.Y) > NetConfig.MaxPhysicsBodyVelocity)
|
|
||||||
{
|
|
||||||
body.LinearVelocity = new Vector2(
|
|
||||||
MathHelper.Clamp(body.LinearVelocity.X, -NetConfig.MaxPhysicsBodyVelocity, NetConfig.MaxPhysicsBodyVelocity),
|
|
||||||
MathHelper.Clamp(body.LinearVelocity.Y, -NetConfig.MaxPhysicsBodyVelocity, NetConfig.MaxPhysicsBodyVelocity));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateTransform()
|
|
||||||
{
|
|
||||||
Submarine prevSub = Submarine;
|
|
||||||
|
|
||||||
FindHull();
|
|
||||||
|
|
||||||
if (Submarine == null && prevSub != null)
|
|
||||||
{
|
|
||||||
body.SetTransform(body.SimPosition + prevSub.SimPosition, body.Rotation);
|
|
||||||
}
|
|
||||||
else if (Submarine != null && prevSub == null)
|
|
||||||
{
|
|
||||||
body.SetTransform(body.SimPosition - Submarine.SimPosition, body.Rotation);
|
|
||||||
}
|
|
||||||
else if (Submarine != null && prevSub != null && Submarine != prevSub)
|
|
||||||
{
|
|
||||||
body.SetTransform(body.SimPosition + prevSub.SimPosition - Submarine.SimPosition, body.Rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 displayPos = ConvertUnits.ToDisplayUnits(body.SimPosition);
|
|
||||||
rect.X = (int)(displayPos.X - rect.Width / 2.0f);
|
|
||||||
rect.Y = (int)(displayPos.Y + rect.Height / 2.0f);
|
|
||||||
|
|
||||||
if (Math.Abs(body.LinearVelocity.X) > NetConfig.MaxPhysicsBodyVelocity ||
|
|
||||||
Math.Abs(body.LinearVelocity.Y) > NetConfig.MaxPhysicsBodyVelocity)
|
|
||||||
{
|
|
||||||
body.LinearVelocity = new Vector2(
|
|
||||||
MathHelper.Clamp(body.LinearVelocity.X, -NetConfig.MaxPhysicsBodyVelocity, NetConfig.MaxPhysicsBodyVelocity),
|
|
||||||
MathHelper.Clamp(body.LinearVelocity.Y, -NetConfig.MaxPhysicsBodyVelocity, NetConfig.MaxPhysicsBodyVelocity));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Applies buoyancy, drag and angular drag caused by water
|
/// Applies buoyancy, drag and angular drag caused by water
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -514,6 +514,25 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string DisplayName
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string roomName;
|
||||||
|
[Editable, Serialize("", true, translationTextTag: "RoomName.")]
|
||||||
|
public string RoomName
|
||||||
|
{
|
||||||
|
get { return roomName; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (roomName == value) { return; }
|
||||||
|
roomName = value;
|
||||||
|
DisplayName = TextManager.Get(roomName, returnNull: true) ?? roomName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override Rectangle Rect
|
public override Rectangle Rect
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user