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; protected override bool AllowOutsideSubmarine => true; protected override bool AllowInAnySub => true; private int escapeProgress; private bool isBeingWatched; private readonly 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; 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) { foreach (var it in character.HeldItems) { if (it.HasTag(Tags.HandLockerItem) && it.IsInteractable(character)) { it.Drop(character); } } } escapeTimer = EscapeIntervalTimer * Rand.Range(0.75f, 1.25f); } } public override void Reset() { base.Reset(); escapeProgress = 0; } } }