Unstable 0.1500.2.0 (Rokvach's dog edition)
This commit is contained in:
@@ -94,7 +94,7 @@ namespace Barotrauma
|
||||
if (_abandon)
|
||||
{
|
||||
#if DEBUG
|
||||
if (HumanAIController.debugai && objectiveManager.IsOrder(this) && !objectiveManager.IsCurrentOrder<AIObjectiveGoTo>())
|
||||
if (HumanAIController.debugai && objectiveManager.IsOrder(this) && !objectiveManager.IsCurrentOrder<AIObjectiveGoTo>() && !objectiveManager.IsCurrentOrder<AIObjectiveReturn>())
|
||||
{
|
||||
throw new Exception("Order abandoned!");
|
||||
}
|
||||
|
||||
+7
-6
@@ -83,12 +83,13 @@ namespace Barotrauma
|
||||
if (suitableContainer != null)
|
||||
{
|
||||
bool equip = item.GetComponent<Holdable>() != null ||
|
||||
item.AllowedSlots.None(s =>
|
||||
s == InvSlotType.Card ||
|
||||
s == InvSlotType.Head ||
|
||||
s == InvSlotType.Headset ||
|
||||
s == InvSlotType.InnerClothes ||
|
||||
s == InvSlotType.OuterClothes);
|
||||
item.AllowedSlots.Any(s => s != InvSlotType.Any) &&
|
||||
item.AllowedSlots.None(s =>
|
||||
s == InvSlotType.Card ||
|
||||
s == InvSlotType.Head ||
|
||||
s == InvSlotType.Headset ||
|
||||
s == InvSlotType.InnerClothes ||
|
||||
s == InvSlotType.OuterClothes);
|
||||
|
||||
TryAddSubObjective(ref decontainObjective, () => new AIObjectiveDecontainItem(character, item, objectiveManager, targetContainer: suitableContainer.GetComponent<ItemContainer>())
|
||||
{
|
||||
|
||||
+56
-2
@@ -252,9 +252,40 @@ namespace Barotrauma
|
||||
{
|
||||
case CombatMode.Offensive:
|
||||
case CombatMode.Arrest:
|
||||
Engage();
|
||||
Engage(deltaTime);
|
||||
break;
|
||||
case CombatMode.Defensive:
|
||||
if (character.IsOnPlayerTeam && !Enemy.IsPlayer && objectiveManager.IsCurrentOrder<AIObjectiveGoTo>())
|
||||
{
|
||||
if ((character.CurrentHull == null || character.CurrentHull == Enemy.CurrentHull) && sqrDistance < 200 * 200)
|
||||
{
|
||||
Engage(deltaTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Keep following the goto target
|
||||
var gotoObjective = objectiveManager.GetOrder<AIObjectiveGoTo>();
|
||||
if (gotoObjective != null)
|
||||
{
|
||||
gotoObjective.ForceAct(deltaTime);
|
||||
if (!character.AnimController.InWater)
|
||||
{
|
||||
HumanAIController.FaceTarget(Enemy);
|
||||
ForceWalk = true;
|
||||
HumanAIController.AutoFaceMovement = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SteeringManager.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Retreat(deltaTime);
|
||||
}
|
||||
break;
|
||||
case CombatMode.Retreat:
|
||||
Retreat(deltaTime);
|
||||
break;
|
||||
@@ -671,6 +702,14 @@ namespace Barotrauma
|
||||
{
|
||||
RemoveSubObjective(ref retreatObjective);
|
||||
}
|
||||
if (character.Submarine == null && sqrDistance < MathUtils.Pow2(maxDistance))
|
||||
{
|
||||
// Swim away
|
||||
SteeringManager.Reset();
|
||||
SteeringManager.SteeringManual(deltaTime, Vector2.Normalize(character.WorldPosition - Enemy.WorldPosition));
|
||||
SteeringManager.SteeringAvoid(deltaTime, 5, weight: 2);
|
||||
return;
|
||||
}
|
||||
if (retreatTarget == null || (retreatObjective != null && !retreatObjective.CanBeCompleted))
|
||||
{
|
||||
if (findHullTimer > 0)
|
||||
@@ -704,7 +743,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private void Engage()
|
||||
private void Engage(float deltaTime)
|
||||
{
|
||||
if (WeaponComponent == null)
|
||||
{
|
||||
@@ -722,6 +761,21 @@ namespace Barotrauma
|
||||
RemoveSubObjective(ref retreatObjective);
|
||||
RemoveSubObjective(ref seekAmmunitionObjective);
|
||||
RemoveSubObjective(ref seekWeaponObjective);
|
||||
if (character.Submarine == null && WeaponComponent is MeleeWeapon meleeWeapon)
|
||||
{
|
||||
if (sqrDistance > MathUtils.Pow2(meleeWeapon.Range))
|
||||
{
|
||||
// Swim towards the target
|
||||
SteeringManager.Reset();
|
||||
SteeringManager.SteeringSeek(character.GetRelativeSimPosition(Enemy), weight: 10);
|
||||
SteeringManager.SteeringAvoid(deltaTime, 5, weight: 15);
|
||||
}
|
||||
else
|
||||
{
|
||||
SteeringManager.Reset();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (followTargetObjective != null && followTargetObjective.Target != Enemy)
|
||||
{
|
||||
RemoveFollowTarget();
|
||||
|
||||
+21
-21
@@ -46,7 +46,10 @@ namespace Barotrauma
|
||||
}
|
||||
if (character.CurrentHull == null)
|
||||
{
|
||||
Priority = (objectiveManager.IsCurrentOrder<AIObjectiveGoTo>() || objectiveManager.HasActiveObjective<AIObjectiveCombat>()) && HumanAIController.HasDivingSuit(character) ? 0 : 100;
|
||||
Priority = (objectiveManager.IsCurrentOrder<AIObjectiveGoTo>() ||
|
||||
objectiveManager.IsCurrentOrder<AIObjectiveReturn>() ||
|
||||
objectiveManager.Objectives.Any(o => o.Priority > 0 && o is AIObjectiveCombat))
|
||||
&& HumanAIController.HasDivingSuit(character) ? 0 : 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -57,9 +60,11 @@ namespace Barotrauma
|
||||
{
|
||||
Priority = 100;
|
||||
}
|
||||
else if (objectiveManager.IsCurrentOrder<AIObjectiveGoTo>() && character.Submarine != null && !HumanAIController.IsOnFriendlyTeam(character.TeamID, character.Submarine.TeamID))
|
||||
else if ((objectiveManager.IsCurrentOrder<AIObjectiveGoTo>() || objectiveManager.IsCurrentOrder<AIObjectiveReturn>()) &&
|
||||
character.Submarine != null && !HumanAIController.IsOnFriendlyTeam(character.TeamID, character.Submarine.TeamID))
|
||||
{
|
||||
// Ordered to follow/hold position inside a hostile sub -> ignore find safety unless we need to find a diving gear
|
||||
// Ordered to follow, hold position, or return back to main sub inside a hostile sub
|
||||
// -> ignore find safety unless we need to find a diving gear
|
||||
Priority = 0;
|
||||
}
|
||||
Priority = MathHelper.Clamp(Priority, 0, 100);
|
||||
@@ -298,6 +303,7 @@ namespace Barotrauma
|
||||
|
||||
Hull bestHull = null;
|
||||
float bestValue = 0;
|
||||
bool bestIsAirlock = false;
|
||||
foreach (Hull hull in Hull.hullList.OrderByDescending(h => EstimateHullSuitability(h)))
|
||||
{
|
||||
if (hull.Submarine == null) { continue; }
|
||||
@@ -306,9 +312,10 @@ namespace Barotrauma
|
||||
if (ignoredHulls != null && ignoredHulls.Contains(hull)) { continue; }
|
||||
if (HumanAIController.UnreachableHulls.Contains(hull)) { continue; }
|
||||
float hullSafety = 0;
|
||||
if (character.CurrentHull != null && character.Submarine != null)
|
||||
bool hullIsAirlock = false;
|
||||
bool isCharacterInside = character.CurrentHull != null && character.Submarine != null;
|
||||
if (isCharacterInside)
|
||||
{
|
||||
// Inside
|
||||
if (!character.Submarine.IsConnectedTo(hull.Submarine)) { continue; }
|
||||
hullSafety = HumanAIController.GetHullSafety(hull, hull.GetConnectedHulls(true, 1), character);
|
||||
float yDist = Math.Abs(character.WorldPosition.Y - hull.WorldPosition.Y);
|
||||
@@ -343,24 +350,16 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
// Outside
|
||||
if (hull.RoomName != null && hull.RoomName.Contains("airlock", StringComparison.OrdinalIgnoreCase))
|
||||
// TODO: could also target gaps that get us inside?
|
||||
if (hull.IsTaggedAirlock())
|
||||
{
|
||||
hullSafety = 100;
|
||||
hullIsAirlock = true;
|
||||
}
|
||||
else if(!bestIsAirlock && hull.LeadsOutside(character))
|
||||
{
|
||||
hullSafety = 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: could also target gaps that get us inside?
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
if (item.CurrentHull != hull && item.HasTag("airlock"))
|
||||
{
|
||||
hullSafety = 100;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: could we get a closest door to the outside and target the flowing hull if no airlock is found?
|
||||
// Huge preference for closer targets
|
||||
float distance = Vector2.DistanceSquared(character.WorldPosition, hull.WorldPosition);
|
||||
float distanceFactor = MathHelper.Lerp(1, 0.2f, MathUtils.InverseLerp(0, MathUtils.Pow(100000, 2), distance));
|
||||
@@ -372,10 +371,11 @@ namespace Barotrauma
|
||||
hullSafety /= 10;
|
||||
}
|
||||
}
|
||||
if (hullSafety > bestValue)
|
||||
if (hullSafety > bestValue || (!isCharacterInside && hullIsAirlock && !bestIsAirlock))
|
||||
{
|
||||
bestHull = hull;
|
||||
bestValue = hullSafety;
|
||||
bestIsAirlock = hullIsAirlock;
|
||||
}
|
||||
}
|
||||
return bestHull;
|
||||
|
||||
+13
-2
@@ -159,6 +159,8 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public void ForceAct(float deltaTime) => Act(deltaTime);
|
||||
|
||||
protected override void Act(float deltaTime)
|
||||
{
|
||||
if (followControlledCharacter)
|
||||
@@ -240,7 +242,7 @@ namespace Barotrauma
|
||||
if (getDivingGearIfNeeded && !character.LockHands)
|
||||
{
|
||||
Character followTarget = Target as Character;
|
||||
bool needsDivingSuit = targetIsOutside;
|
||||
bool needsDivingSuit = !isInside || targetIsOutside;
|
||||
bool needsDivingGear = needsDivingSuit || HumanAIController.NeedsDivingGear(targetHull, out needsDivingSuit);
|
||||
if (mimic)
|
||||
{
|
||||
@@ -444,13 +446,22 @@ namespace Barotrauma
|
||||
}
|
||||
if (SteeringManager == PathSteering)
|
||||
{
|
||||
Vector2 targetPos = character.GetRelativeSimPosition(Target);
|
||||
Func<PathNode, bool> nodeFilter = null;
|
||||
if (isInside && !AllowGoingOutside)
|
||||
{
|
||||
nodeFilter = n => n.Waypoint.CurrentHull != null;
|
||||
}
|
||||
else if (!isInside && HumanAIController.UseIndoorSteeringOutside)
|
||||
{
|
||||
if (character.Submarine == null && Target.Submarine != null)
|
||||
{
|
||||
targetPos += Target.Submarine.SimPosition;
|
||||
}
|
||||
nodeFilter = n => n.Waypoint.Tunnel != null;
|
||||
}
|
||||
|
||||
PathSteering.SteeringSeek(character.GetRelativeSimPosition(Target), 1,
|
||||
PathSteering.SteeringSeek(targetPos, 1,
|
||||
startNodeFilter: n => (n.Waypoint.CurrentHull == null) == (character.CurrentHull == null),
|
||||
endNodeFilter,
|
||||
nodeFilter,
|
||||
|
||||
+31
-7
@@ -233,11 +233,7 @@ namespace Barotrauma
|
||||
if (orderObjective == null) { return; }
|
||||
#if DEBUG
|
||||
// Note: don't automatically remove orders here. Removing orders needs to be done via dismissing.
|
||||
if (orderObjective.IsCompleted)
|
||||
{
|
||||
DebugConsole.NewMessage($"{character.Name}: ORDER {orderObjective.DebugTag} IS COMPLETED. CURRENTLY ALL ORDERS SHOULD BE LOOPING.", Color.Red);
|
||||
}
|
||||
else if (!orderObjective.CanBeCompleted)
|
||||
if (!orderObjective.CanBeCompleted)
|
||||
{
|
||||
DebugConsole.NewMessage($"{character.Name}: ORDER {orderObjective.DebugTag}, CANNOT BE COMPLETED.", Color.Red);
|
||||
}
|
||||
@@ -281,9 +277,9 @@ namespace Barotrauma
|
||||
ForcedOrder?.CalculatePriority();
|
||||
AIObjective orderWithHighestPriority = null;
|
||||
float highestPriority = 0;
|
||||
foreach (var currentOrder in CurrentOrders)
|
||||
for (int i = CurrentOrders.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var orderObjective = currentOrder.Objective;
|
||||
var orderObjective = CurrentOrders[i].Objective;
|
||||
if (orderObjective == null) { continue; }
|
||||
orderObjective.CalculatePriority();
|
||||
if (orderWithHighestPriority == null || orderObjective.Priority > highestPriority)
|
||||
@@ -467,6 +463,11 @@ namespace Barotrauma
|
||||
AllowGoingOutside = character.Submarine == null || (order.TargetSpatialEntity != null && character.Submarine != order.TargetSpatialEntity.Submarine)
|
||||
};
|
||||
break;
|
||||
case "return":
|
||||
newObjective = new AIObjectiveReturn(character, this, priorityModifier: priorityModifier);
|
||||
newObjective.Abandoned += () => DismissSelf(order, option);
|
||||
newObjective.Completed += () => DismissSelf(order, option);
|
||||
break;
|
||||
case "fixleaks":
|
||||
newObjective = new AIObjectiveFixLeaks(character, this, priorityModifier: priorityModifier, prioritizedHull: order.TargetEntity as Hull);
|
||||
break;
|
||||
@@ -586,6 +587,27 @@ namespace Barotrauma
|
||||
return newObjective;
|
||||
}
|
||||
|
||||
private void DismissSelf(Order order, string option)
|
||||
{
|
||||
var currentOrder = CurrentOrders.FirstOrDefault(oi => oi.MatchesOrder(order, option));
|
||||
if (currentOrder.Order == null)
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError("Tried to self-dismiss an order, but no matching current order was found");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
#if CLIENT
|
||||
if (GameMain.GameSession?.CrewManager != null && GameMain.GameSession.CrewManager.IsSinglePlayer)
|
||||
{
|
||||
GameMain.GameSession?.CrewManager?.SetCharacterOrder(character, Order.GetPrefab("dismissed"), Order.GetDismissOrderOption(currentOrder), currentOrder.ManualPriority, character);
|
||||
}
|
||||
#else
|
||||
GameMain.Server?.SendOrderChatMessage(new OrderChatMessage(Order.GetPrefab("dismissed"), Order.GetDismissOrderOption(currentOrder), currentOrder.ManualPriority, currentOrder.Order?.TargetSpatialEntity, character, character));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
private bool IsAllowedToWait()
|
||||
{
|
||||
if (!character.IsOnPlayerTeam) { return false; }
|
||||
@@ -606,6 +628,8 @@ namespace Barotrauma
|
||||
public bool IsActiveObjective<T>() where T : AIObjective => GetActiveObjective() is T;
|
||||
|
||||
public AIObjective GetActiveObjective() => CurrentObjective?.GetActiveObjective();
|
||||
public T GetOrder<T>() where T : AIObjective => CurrentOrders.FirstOrDefault(o => o.Objective is T).Objective as T;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the last active objective of the specific type.
|
||||
/// </summary>
|
||||
|
||||
+243
@@ -0,0 +1,243 @@
|
||||
using Barotrauma.Extensions;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class AIObjectiveReturn : AIObjective
|
||||
{
|
||||
public override string Identifier { get; set; } = "return";
|
||||
private AIObjectiveGoTo moveInsideObjective, moveInCaveObjective, moveOutsideObjective;
|
||||
private bool usingEscapeBehavior;
|
||||
public Submarine ReturnTarget { get; }
|
||||
|
||||
public AIObjectiveReturn(Character character, AIObjectiveManager objectiveManager, float priorityModifier = 1.0f) : base(character, objectiveManager, priorityModifier)
|
||||
{
|
||||
ReturnTarget = GetReturnTarget(Submarine.MainSubs) ?? GetReturnTarget(Submarine.Loaded);
|
||||
if (ReturnTarget == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Error with a Return objective: no suitable return target found");
|
||||
Abandon = true;
|
||||
}
|
||||
|
||||
Submarine GetReturnTarget(IEnumerable<Submarine> subs)
|
||||
{
|
||||
Submarine returnTarget = null;
|
||||
foreach (var sub in subs)
|
||||
{
|
||||
if (sub?.TeamID != character.TeamID) { continue; }
|
||||
returnTarget = sub;
|
||||
break;
|
||||
}
|
||||
return returnTarget;
|
||||
}
|
||||
}
|
||||
|
||||
protected override float GetPriority()
|
||||
{
|
||||
if (!Abandon && !IsCompleted && objectiveManager.IsOrder(this))
|
||||
{
|
||||
Priority = objectiveManager.GetOrderPriority(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Consider if this needs to be addressed
|
||||
Priority = 0;
|
||||
}
|
||||
return Priority;
|
||||
}
|
||||
|
||||
protected override void Act(float deltaTime)
|
||||
{
|
||||
if (ReturnTarget == null)
|
||||
{
|
||||
Abandon = true;
|
||||
return;
|
||||
}
|
||||
bool shouldUseEscapeBehavior = false;
|
||||
if (character.CurrentHull != null)
|
||||
{
|
||||
if (character.Submarine == null || !character.Submarine.IsConnectedTo(ReturnTarget))
|
||||
{
|
||||
// Character is on another sub that is not connected to the target sub, use the escape behavior to get them out
|
||||
shouldUseEscapeBehavior = true;
|
||||
if (!usingEscapeBehavior)
|
||||
{
|
||||
HumanAIController.ResetEscape();
|
||||
}
|
||||
HumanAIController.Escape(deltaTime);
|
||||
if (HumanAIController.EscapeTarget == null || !HumanAIController.HasValidPath(requireNonDirty: true, requireUnfinished: false))
|
||||
{
|
||||
Abandon = true;
|
||||
}
|
||||
}
|
||||
else if (character.Submarine != ReturnTarget)
|
||||
{
|
||||
// Character is on another sub that is connected to the target sub, create a Go To objective to reach the target sub
|
||||
if (moveInsideObjective == null)
|
||||
{
|
||||
Hull targetHull = null;
|
||||
foreach (var d in ReturnTarget.ConnectedDockingPorts.Values)
|
||||
{
|
||||
if (!d.Docked) { continue; }
|
||||
if (d.DockingTarget == null) { continue; }
|
||||
if (d.DockingTarget.Item.Submarine != character.Submarine) { continue; }
|
||||
targetHull = d.Item.CurrentHull;
|
||||
break;
|
||||
}
|
||||
if (targetHull != null)
|
||||
{
|
||||
RemoveSubObjective(ref moveInCaveObjective);
|
||||
RemoveSubObjective(ref moveOutsideObjective);
|
||||
// TODO: Check 'repeat' and 'onAbandon' parameters
|
||||
TryAddSubObjective(ref moveInsideObjective,
|
||||
constructor: () => new AIObjectiveGoTo(targetHull, character, objectiveManager),
|
||||
onCompleted: () => moveInsideObjective = null);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError("Error with a Return objective: no suitable target for 'moveInsideObjective'");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Character is on the target sub, the objective is completed
|
||||
IsCompleted = true;
|
||||
}
|
||||
}
|
||||
else if (moveInCaveObjective == null && moveOutsideObjective == null)
|
||||
{
|
||||
if (HumanAIController.IsInsideCave)
|
||||
{
|
||||
WayPoint closestOutsideWaypoint = null;
|
||||
float closestDistance = float.MaxValue;
|
||||
foreach (var w in WayPoint.WayPointList)
|
||||
{
|
||||
if (w.Tunnel == null) { continue; }
|
||||
if (w.Tunnel.Type == Level.TunnelType.Cave) { continue; }
|
||||
if (w.linkedTo.None(l => l is WayPoint linkedWaypoint && linkedWaypoint.Tunnel?.Type == Level.TunnelType.Cave)) { continue; }
|
||||
float distance = Vector2.DistanceSquared(character.WorldPosition, w.WorldPosition);
|
||||
if (closestOutsideWaypoint == null || distance < closestDistance)
|
||||
{
|
||||
closestOutsideWaypoint = w;
|
||||
closestDistance = distance;
|
||||
}
|
||||
}
|
||||
if (closestOutsideWaypoint != null)
|
||||
{
|
||||
RemoveSubObjective(ref moveInsideObjective);
|
||||
RemoveSubObjective(ref moveOutsideObjective);
|
||||
// TODO: Check 'repeat' and 'onAbandon' parameters
|
||||
TryAddSubObjective(ref moveInCaveObjective,
|
||||
constructor: () => new AIObjectiveGoTo(closestOutsideWaypoint, character, objectiveManager)
|
||||
{
|
||||
endNodeFilter = n => n.Waypoint == closestOutsideWaypoint
|
||||
},
|
||||
onCompleted: () => moveInCaveObjective = null);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError("Error with a Return objective: no suitable main or side path node target found for 'moveOutsideObjective'");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Hull targetHull = null;
|
||||
float targetDistanceSquared = float.MaxValue;
|
||||
bool targetIsAirlock = false;
|
||||
foreach (var hull in ReturnTarget.GetHulls(false))
|
||||
{
|
||||
bool hullIsAirlock = hull.IsTaggedAirlock();
|
||||
if(hullIsAirlock || (!targetIsAirlock && hull.LeadsOutside(character)))
|
||||
{
|
||||
float distanceSquared = Vector2.DistanceSquared(character.WorldPosition, hull.WorldPosition);
|
||||
if (targetHull == null || distanceSquared < targetDistanceSquared)
|
||||
{
|
||||
targetHull = hull;
|
||||
targetDistanceSquared = distanceSquared;
|
||||
targetIsAirlock = hullIsAirlock;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (targetHull != null)
|
||||
{
|
||||
RemoveSubObjective(ref moveInsideObjective);
|
||||
RemoveSubObjective(ref moveInCaveObjective);
|
||||
// TODO: Check 'repeat' and 'onAbandon' parameters
|
||||
TryAddSubObjective(ref moveOutsideObjective,
|
||||
constructor: () => new AIObjectiveGoTo(targetHull, character, objectiveManager),
|
||||
onCompleted: () => moveOutsideObjective = null);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError("Error with a Return objective: no suitable target for 'moveOutsideObjective'");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (HumanAIController.IsInsideCave)
|
||||
{
|
||||
if (moveOutsideObjective != null)
|
||||
{
|
||||
RemoveSubObjective(ref moveOutsideObjective);
|
||||
moveOutsideObjective = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (moveInCaveObjective != null)
|
||||
{
|
||||
RemoveSubObjective(ref moveInCaveObjective);
|
||||
moveInCaveObjective = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
usingEscapeBehavior = shouldUseEscapeBehavior;
|
||||
}
|
||||
|
||||
protected override bool CheckObjectiveSpecific()
|
||||
{
|
||||
if (IsCompleted)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (ReturnTarget == null)
|
||||
{
|
||||
Abandon = true;
|
||||
return false;
|
||||
}
|
||||
if (character.Submarine == ReturnTarget)
|
||||
{
|
||||
IsCompleted = true;
|
||||
}
|
||||
return IsCompleted;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
moveInsideObjective = null;
|
||||
moveInCaveObjective = null;
|
||||
moveOutsideObjective = null;
|
||||
usingEscapeBehavior = false;
|
||||
HumanAIController.ResetEscape();
|
||||
}
|
||||
|
||||
protected override void OnAbandon()
|
||||
{
|
||||
base.OnAbandon();
|
||||
SteeringManager.Reset();
|
||||
if (character.IsOnPlayerTeam && objectiveManager.CurrentOrder == objectiveManager.CurrentObjective)
|
||||
{
|
||||
string msg = TextManager.Get("dialogcannotreturn", returnNull: true);
|
||||
if (msg != null)
|
||||
{
|
||||
character.Speak(msg, identifier: "dialogcannotreturn", minDurationBetweenSimilar: 5.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user