2 using System.Collections.Generic;
4 using Microsoft.Xna.Framework;
6 using System.Collections.Immutable;
73 protected readonly List<AIObjective>
subObjectives =
new List<AIObjective>();
74 private float _cumulatedDevotion;
77 get {
return _cumulatedDevotion; }
78 set { _cumulatedDevotion = MathHelper.Clamp(value, 0,
MaxDevotion); }
88 private float resetPriorityTimer;
89 private readonly
float resetPriorityTime = 1;
90 private bool _forceHighestPriority;
94 get {
return _forceHighestPriority; }
97 if (_forceHighestPriority == value) {
return; }
98 _forceHighestPriority = value;
99 if (_forceHighestPriority)
101 resetPriorityTimer = resetPriorityTime;
116 private bool _abandon;
119 get {
return _abandon; }
134 private readonly List<AIObjective> all =
new List<AIObjective>();
145 all.AddRange(subObjective.GetSubObjectivesRecursive(
true));
195 if (isCompleted) {
return; }
196 if (CheckState()) {
return; }
208 var type = objective.GetType();
223 if (objective !=
null)
239 subObjectives.Sort((x, y) => y.Priority.CompareTo(x.Priority));
247 if (previousSubObjective != currentSubObjective)
249 previousSubObjective.OnDeselected();
250 currentSubObjective.OnSelected();
252 currentSubObjective.SortSubObjectives();
331 public static float GetDistanceFactor(Vector2 selfPos, Vector2 targetWorldPos,
float factorAtMaxDistance,
float verticalDistanceMultiplier = 3,
float maxDistance = 10000.0f,
float factorAtMinDistance = 1.0f)
333 float yDist = Math.Abs(selfPos.Y - targetWorldPos.Y);
334 yDist = yDist > 100 ? yDist * verticalDistanceMultiplier : 0;
335 float distance = Math.Abs(selfPos.X - targetWorldPos.X) + yDist;
336 float distanceFactor = MathHelper.Lerp(factorAtMinDistance, factorAtMaxDistance, MathUtils.InverseLerp(0, maxDistance, distance));
338 factorAtMinDistance > factorAtMaxDistance ?
339 MathHelper.Clamp(distanceFactor, factorAtMaxDistance, factorAtMinDistance) :
340 MathHelper.Clamp(distanceFactor, factorAtMinDistance, factorAtMaxDistance);
352 protected float GetDistanceFactor(Vector2 targetWorldPos,
float factorAtMaxDistance,
float verticalDistanceMultiplier = 3,
float maxDistance = 10000.0f,
float factorAtMinDistance = 1.0f)
357 private void UpdateDevotion(
float deltaTime)
360 if (currentObjective !=
null && (currentObjective ==
this || currentObjective.subObjectives.FirstOrDefault() ==
this))
368 public virtual void Update(
float deltaTime)
370 if (resetPriorityTimer > 0)
372 resetPriorityTimer -= deltaTime;
380 UpdateDevotion(deltaTime);
390 foreach (T1 key
in collection)
392 if (dictionary.TryGetValue(key, out T2 objective))
396 dictionary.Remove(key);
409 if (objective !=
null)
421 objective = constructor();
424 if (objective.AllowMultipleInstances)
426 objective.SourceObjective =
this;
433 if (onCompleted !=
null)
435 objective.Completed += onCompleted;
437 if (onAbandon !=
null)
439 objective.Abandoned += onAbandon;
444 DebugConsole.ThrowError(
"Attempted to add a duplicate subobjective!\n" + Environment.StackTrace.CleanupStackTrace());
480 hasBeenChecked =
false;
485 protected abstract void Act(
float deltaTime);
487 private bool isCompleted;
488 private bool hasBeenChecked;
502 if (isCompleted == value) {
return; }
516 if (isCompleted) {
return true; }
530 private bool CheckState()
532 hasBeenChecked =
true;
533 CheckSubObjectives();
544 private void CheckSubObjectives()
549 subObjective.CheckState();
550 if (subObjective.IsCompleted)
553 DebugConsole.NewMessage($
"{character.Name}: Removing SUBobjective {subObjective.DebugTag} of {DebugTag}, because it is completed.", Color.LightGreen);
557 else if (!subObjective.CanBeCompleted)
560 DebugConsole.NewMessage($
"{character.Name}: Removing SUBobjective {subObjective.DebugTag} of {DebugTag}, because it cannot be completed.", Color.Red);
580 if (item ==
null) {
return false; }
581 bool canEquip =
false;
601 foreach (var slotType
in inv.SlotTypes)
603 if (!allowedSlot.HasFlag(slotType)) {
continue; }
604 for (
int i = 0; i < inv.Capacity; i++)
607 if (allowedSlot.HasFlag(inv.SlotTypes[i]) && inv.GetItemAt(i) !=
null)
SteeringManager SteeringManager
virtual bool IsDuplicate< T >(T otherObjective)
IEnumerable< AIObjective > SubObjectives
virtual bool IgnoreUnsafeHulls
bool IsIgnoredAtOutpost()
Returns true only when at a friendly outpost and when the order is set to be ignored there....
virtual bool AbandonIfDisallowed
Should the objective abandon when it's not allowed in the current context or should it just stay inac...
float CalculatePriority()
Call this only when the priority needs to be recalculated. Use the cached Priority property when you ...
AIObjective CurrentSubObjective
void RemoveSubObjective< T >(ref T objective)
virtual bool AllowInAnySub
virtual bool CanBeCompleted
virtual bool KeepDivingGearOnAlsoWhenInactive
AIObjective SourceObjective
Which objective (if any) created this objective. When this is a subobjective, the parent objective is...
EventAction SourceEventAction
Which event action (if any) created this objective
virtual bool AllowMultipleInstances
Can there be multiple objective instaces of the same type?
virtual void Update(float deltaTime)
IEnumerable< AIObjective > GetSubObjectivesRecursive(bool includingSelf=false)
float Priority
Final priority value after all calculations.
Action Selected
A single shot event. Automatically cleared after launching. Use OnSelected method for implementing (i...
abstract void Act(float deltaTime)
void AddSubObjective(AIObjective objective, bool addFirst=false)
virtual bool AllowWhileHandcuffed
readonly Character character
AIObjective GetActiveObjective()
Action Deselected
A single shot event. Automatically cleared after launching. Use OnDeselected method for implementing ...
Func< AIObjective, bool > AbortCondition
Aborts the objective when this condition is true.
void TryComplete(float deltaTime)
Makes the character act according to the objective, or according to any subobjectives that need to be...
virtual float GetPriority()
virtual bool KeepDivingGearOn
virtual float MaxDevotion
bool TryAddSubObjective< T >(ref T objective, Func< T > constructor, Action onCompleted=null, Action onAbandon=null)
Checks if the objective already is created and added in subobjectives. If not, creates it....
bool CanEquip(Item item, bool allowWearing)
virtual void SyncRemovedObjectives< T1, T2 >(Dictionary< T1, T2 > dictionary, IEnumerable< T1 > collection)
Checks if the subobjectives in the given collection are removed from the subobjectives....
IndoorsSteeringManager PathSteering
HumanAIController HumanAIController
readonly List< AIObjective > subObjectives
bool ForceHighestPriority
virtual bool AbandonWhenCannotCompleteSubObjectives
AIObjective(Character character, AIObjectiveManager objectiveManager, float priorityModifier, Identifier option=default)
Action Completed
A single shot event. Automatically cleared after launching. Use OnCompleted method for implementing (...
virtual bool AllowOutsideSubmarine
readonly Identifier Option
virtual bool PrioritizeIfSubObjectivesActive
Action Abandoned
A single shot event. Automatically cleared after launching. Use OnAbandoned method for implementing (...
virtual void OnSelected()
virtual void OnCompleted()
virtual bool AllowInFriendlySubs
When true, the objective is allowed in the player subs (when in the same team) and on friendly outpos...
static bool CanPutInInventory(Character character, Item item, bool allowWearing)
virtual bool AllowAutomaticItemUnequipping
There's a separate property for diving suit and mask: KeepDivingGearOn.
abstract bool CheckObjectiveState()
Should return whether the objective is completed or not.
readonly AIObjectiveManager objectiveManager
virtual bool AllowSubObjectiveSorting
Should subobjectives be sorted according to their priority?
float GetDistanceFactor(Vector2 targetWorldPos, float factorAtMaxDistance, float verticalDistanceMultiplier=3, float maxDistance=10000.0f, float factorAtMinDistance=1.0f)
Get a normalized value representing how close the target position is. The value is a rough estimation...
virtual bool ConcurrentObjectives
Run the main objective with all subobjectives concurrently? If false, the main objective will continu...
virtual void OnDeselected()
abstract Identifier Identifier
static float GetDistanceFactor(Vector2 selfPos, Vector2 targetWorldPos, float factorAtMaxDistance, float verticalDistanceMultiplier=3, float maxDistance=10000.0f, float factorAtMinDistance=1.0f)
Get a normalized value representing how close the target position is. The value is a rough estimation...
AIObjective CurrentObjective
Includes orders.
float GetOrderPriority(AIObjective objective)
bool IsOrder(AIObjective objective)
float? WaitTimer
When set above zero, the character will stand still doing nothing until the timer runs out....
virtual AIController AIController
CharacterTeamType?? OriginalTeamID
bool IsFriendlyNPCTurnedHostile
CharacterInventory Inventory
bool IsAnySlotAvailable(Item item)
virtual Vector2 WorldPosition
IndoorsSteeringManager PathSteering
bool CanBePut(Item item)
Can the item be put in the inventory (i.e. is there a suitable free slot or a stack the item can be p...
IEnumerable< InvSlotType > AllowedSlots
static bool IsLoadedFriendlyOutpost
Is there a loaded level set, and is it a friendly outpost (FriendlyNPC or Team1). Does not take reput...