2 using Microsoft.Xna.Framework;
4 using System.Collections.Generic;
17 get {
return active; }
20 active = value ? TryInitializeShipCommandManager() : value;
47 float navigationTimer = 0f;
48 private readonly
float navigationInterval = 4f;
51 private const float RamTimerMax = 17.5f;
55 private const float IssueDevotionBuffer = 5f;
57 private float decisionTimer = 6f;
58 private readonly
float decisionInterval = 6f;
60 private float timeSinceLastCommandDecision;
61 private float timeSinceLastNavigation;
66 private readonly List<ShipIssueWorker> attendedIssues =
new List<ShipIssueWorker>();
67 private readonly List<ShipIssueWorker> availableIssues =
new List<ShipIssueWorker>();
68 private readonly List<ShipGlobalIssue> shipGlobalIssues =
new List<ShipGlobalIssue>();
79 decisionTimer -= deltaTime;
80 if (decisionTimer <= 0.0f)
82 UpdateCommandDecision(timeSinceLastCommandDecision);
83 decisionTimer = decisionInterval * Rand.Range(0.8f, 1.2f);
84 timeSinceLastCommandDecision = decisionTimer;
87 navigationTimer -= deltaTime;
88 if (navigationTimer <= 0.0f)
90 UpdateNavigation(timeSinceLastNavigation);
91 navigationTimer = navigationInterval * Rand.Range(0.8f, 1.2f);
92 timeSinceLastNavigation = navigationTimer;
98 if (GameSettings.CurrentConfig.VerboseLogging)
100 DebugConsole.NewMessage(text);
104 static bool WithinRange(
float range,
float distanceSquared)
106 return range * range > distanceSquared;
109 void UpdateNavigation(
float timeSinceLastUpdate)
120 if (WithinRange(7000f, distanceSquaredEnemy))
127 else if (WithinRange(40000f, distanceSquaredEnemy))
136 if (WithinRange(8500f, distanceSquaredEnemy) && !WithinRange(1500f, distanceSquaredEnemy))
146 timeUntilRam -= timeSinceLastUpdate;
151 if (timeUntilRam <= 0f)
157 timeUntilRam = RamTimerMax * Rand.Range(0.9f, 1.1f);
164 timeUntilRam = RamTimerMax * Rand.Range(0.9f, 1.1f);
171 if (WithinRange(7000f, distanceSquaredPatrol))
186 void UpdateCommandDecision(
float timeSinceLastUpdate)
193 shipGlobalIssues.ForEach(c => c.CalculateGlobalIssue());
198 bool isEmergency =
false;
204 if (HumanAIController.IsFriendly(
character, potentialCharacter,
true) && potentialCharacter.
AIController is HumanAIController)
221 attendedIssues.Clear();
222 availableIssues.Clear();
226 float importance = shipIssueWorker.CalculateImportance(isEmergency);
227 if (shipIssueWorker.OrderAttendedTo(timeSinceLastUpdate))
230 ShipCommandLog(
"Current importance for " + shipIssueWorker +
" was " + importance +
" and it was already being attended by " + shipIssueWorker.OrderedCharacter);
232 InsertIssue(shipIssueWorker, attendedIssues);
237 ShipCommandLog(
"Current importance for " + shipIssueWorker +
" was " + importance +
" and it is not attended to");
239 shipIssueWorker.RemoveOrder();
240 InsertIssue(shipIssueWorker, availableIssues);
244 static void InsertIssue(ShipIssueWorker issue, List<ShipIssueWorker> list)
247 while (index < list.Count && list[index].Importance > issue.Importance)
251 list.Insert(index, issue);
254 ShipIssueWorker mostImportantIssue = availableIssues.FirstOrDefault();
256 float bestValue = 0f;
261 IEnumerable<Character> bestCharacters = CrewManager.GetCharactersSortedForOrder(mostImportantIssue.SuggestedOrder,
AlliedCharacters,
character,
true);
263 foreach (Character orderedCharacter
in bestCharacters)
265 float issueApplicability = mostImportantIssue.Importance;
268 issueApplicability *= mostImportantIssue.SuggestedOrder.AppropriateJobs.Contains(orderedCharacter.Info.Job.Prefab.Identifier) ? 1f : 0.75f;
270 ShipIssueWorker occupiedIssue = attendedIssues.FirstOrDefault(i => i.OrderedCharacter == orderedCharacter);
272 if (occupiedIssue !=
null)
274 if (occupiedIssue.GetType() == mostImportantIssue.GetType() && mostImportantIssue is ShipIssueWorkerGlobal && occupiedIssue is ShipIssueWorkerGlobal)
280 if (mostImportantIssue.AllowEasySwitching && occupiedIssue.AllowEasySwitching)
282 issueApplicability /= mostImportantIssue.CurrentRedundancy;
286 issueApplicability += occupiedIssue.SuggestedOrder.AppropriateJobs.Contains(orderedCharacter.Info.Job.Prefab.Identifier) ? 0 : 7.5f;
289 issueApplicability -= IssueDevotionBuffer;
291 if (issueApplicability + IssueDevotionBuffer < occupiedIssue.Importance)
298 if (issueApplicability > bestValue)
300 bestValue = issueApplicability;
301 bestCharacter = orderedCharacter;
306 if (bestCharacter !=
null && mostImportantIssue !=
null)
309 ShipCommandLog(
"Setting " + mostImportantIssue +
" for character " + bestCharacter);
311 mostImportantIssue.SetOrder(bestCharacter);
317 if (shipIssueWorker.Importance <= 0f && shipIssueWorker.OrderAttendedTo())
320 ShipCommandLog(
"Dismissing " + shipIssueWorker +
" for character " + shipIssueWorker.OrderedCharacter);
322 var order =
new Order(OrderPrefab.Dismissal,
null).WithManualPriority(3).WithOrderGiver(
character);
323 shipIssueWorker.OrderedCharacter.SetOrder(order, isNewOrder:
true);
324 shipIssueWorker.RemoveOrder();
331 bool TryInitializeShipCommandManager()
337 DebugConsole.ThrowError(
"TryInitializeShipCommandManager failed: CommandedSubmarine was null for character " +
character);
345 DebugConsole.ThrowError(
"TryInitializeShipCommandManager failed: EnemySubmarine was null for character " +
character);
349 timeUntilRam = RamTimerMax * Rand.Range(0.9f, 1.1f);
355 var order =
new Order(OrderPrefab.Prefabs[
"operatereactor"],
"powerup".ToIdentifier(), reactor.Item, reactor);
361 steering = steeringComponent;
362 var order =
new Order(OrderPrefab.Prefabs[
"steer"],
"navigatetactical".ToIdentifier(), nav, steeringComponent);
368 var order =
new Order(OrderPrefab.Prefabs[
"operateweapons"], item, item.GetComponent<
Turret>());
372 int crewSizeModifier = 2;
374 ShipGlobalIssueFixLeaks shipGlobalIssueFixLeaks =
new ShipGlobalIssueFixLeaks(
this);
375 for (
int i = 0; i < crewSizeModifier; i++)
377 var order = OrderPrefab.Prefabs[
"fixleaks"].CreateInstance(OrderPrefab.OrderTargetType.Entity);
378 ShipIssueWorkers.Add(
new ShipIssueWorkerFixLeaks(
this, order, shipGlobalIssueFixLeaks));
380 shipGlobalIssues.Add(shipGlobalIssueFixLeaks);
382 ShipGlobalIssueRepairSystems shipGlobalIssueRepairSystems =
new ShipGlobalIssueRepairSystems(
this);
383 for (
int i = 0; i < crewSizeModifier; i++)
385 var order = OrderPrefab.Prefabs[
"repairsystems"].CreateInstance(OrderPrefab.OrderTargetType.Entity);
386 ShipIssueWorkers.Add(
new ShipIssueWorkerRepairSystems(
this, order, shipGlobalIssueRepairSystems));
388 shipGlobalIssues.Add(shipGlobalIssueRepairSystems);
virtual AIController AIController
static readonly List< Character > CharacterList
static bool IsActive(Character c)
readonly Character character
readonly HumanAIController humanAIController
ShipCommandManager(Character character)
void Update(float deltaTime)
readonly List< Character > EnemyCharacters
static void ShipCommandLog(string text)
readonly List< Vector2 > patrolPositions
readonly List< ShipIssueWorker > ShipIssueWorkers
bool AbleToTakeOrder(Character character)
Submarine CommandedSubmarine
const float MinimumIssueThreshold
NavigationStates NavigationState
readonly List< Character > AlliedCharacters
List< Item > GetItems(bool alsoFromConnectedSubs)
override Vector2? WorldPosition
@ Character
Characters only