using System; using System.Linq; namespace Barotrauma { class AIObjectiveEscapeHandcuffs : AIObjective { // Used for prisoner escorts to allow them to escape their binds public override Identifier Identifier { get; set; } = "escape handcuffs".ToIdentifier(); public override bool AllowAutomaticItemUnequipping => true; public override bool AllowOutsideSubmarine => true; public override bool AllowInAnySub => true; private int escapeProgress; private bool isBeingWatched; private bool shouldSwitchTeams; const string EscapeTeamChangeIdentifier = "escape"; public AIObjectiveEscapeHandcuffs(Character character, AIObjectiveManager objectiveManager, bool shouldSwitchTeams = true, bool beginInstantly = false, float priorityModifier = 1) : base(character, objectiveManager, priorityModifier) { this.shouldSwitchTeams = shouldSwitchTeams; if (beginInstantly) { escapeTimer = EscapeIntervalTimer; } } public override bool CanBeCompleted => true; public override bool IsLoop { get => true; set => throw new Exception("Trying to set the value for IsLoop from: " + Environment.StackTrace.CleanupStackTrace()); } protected override bool CheckObjectiveSpecific() => false; // escape timer is set to 60 by default to allow players to locate prisoners in time private float escapeTimer = 60f; private const float EscapeIntervalTimer = 7.5f; private float updateTimer; private const float UpdateIntervalTimer = 4f; protected override float GetPriority() { Priority = !isBeingWatched && character.LockHands ? AIObjectiveManager.LowestOrderPriority - 1 : 0; return Priority; } public override void Update(float deltaTime) { updateTimer -= deltaTime; if (updateTimer <= 0.0f) { if (shouldSwitchTeams) { if (!character.LockHands) { if (!character.HasTeamChange(EscapeTeamChangeIdentifier)) { character.TryAddNewTeamChange(EscapeTeamChangeIdentifier, new ActiveTeamChange(CharacterTeamType.None, ActiveTeamChange.TeamChangePriorities.Willful)); } } else { character.TryRemoveTeamChange(EscapeTeamChangeIdentifier); } } isBeingWatched = false; foreach (Character otherCharacter in Character.CharacterList) { if (HumanAIController.IsActive(otherCharacter) && otherCharacter.TeamID == CharacterTeamType.Team1 && HumanAIController.VisibleHulls.Contains(otherCharacter.CurrentHull)) // hasn't been tested yet { isBeingWatched = true; // act casual when player characters are around escapeProgress = 0; break; } } updateTimer = UpdateIntervalTimer * Rand.Range(0.75f, 1.25f); } } protected override void Act(float deltaTime) { SteeringManager.Reset(); escapeTimer -= deltaTime; if (escapeTimer <= 0.0f) { escapeProgress += Rand.Range(2, 5); if (escapeProgress > 15) { Item handcuffs = character.Inventory.FindItemByTag("handlocker".ToIdentifier()); if (handcuffs != null) { handcuffs.Drop(character); } } escapeTimer = EscapeIntervalTimer * Rand.Range(0.75f, 1.25f); } } public override void Reset() { base.Reset(); escapeProgress = 0; } } }