/// <summary> /// Disturbs all Duplicants in range. /// </summary> /// <param name="source">The source of the disturbance.</param> /// <param name="radius">The disturbance radius.</param> internal static void DisturbInRange(GameObject source, float radius) { var effects = Db.Get().effects; Vector2 loc = source.transform.GetPosition(); // Radius is 3 in the base game float radSq = radius * radius; var cells = HashSetPool <int, TraitTemplate> .Allocate(); // Determine who gets disturbed (ouch private method) // Disable cast warning, cast is to ensure correct method selection #pragma warning disable IDE0004 ACOUSTIC_TRAVERSE.CallMethod("DetermineCellsInRadius", Grid.PosToCell(source), 0, Mathf.CeilToInt(radius), (HashSet <int>)cells); #pragma warning restore IDE0004 foreach (var dupe in Components.LiveMinionIdentities.Items) { var newObj = dupe.gameObject; if (newObj != null && newObj != source) { // Is this dupe in range? Vector2 newLoc = dupe.transform.GetPosition(); if (Vector2.SqrMagnitude(loc - newLoc) <= radSq) { int cell = Grid.PosToCell(newLoc); var sleepMonitor = dupe.GetSMI <StaminaMonitor.Instance>(); if (cells.Contains(cell) && (sleepMonitor == null || !sleepMonitor. IsSleeping())) { #if DEBUG PUtil.LogDebug("Disturbing " + newObj.name); #endif // Not happy at hearing snoring newObj.GetSMI <ThoughtGraph.Instance>()?.AddThought(Db.Get(). Thoughts.Unhappy); // Inflict disturbed effect newObj.GetComponent <Effects>()?.Add(effects.Get(TraitTuning. DISTURBED_EFFECT), true); } } } } cells.Recycle(); }