using System.Collections.Generic; using UnityEngine; namespace NecromancerTome { /// /// Нюх одержимой зомбособаки (указание 09.10: «добавь зомбособаке отображение противников, как в Тёмном чутье. /// Типа у собаки нюх»; решено: только в одержимости, чует всех существ). Как Тёмное чутьё змеи /// (SnakeControl.Sense): раз в секунду существа ближе SenseRange к собаке получают метку на компасе и карте, /// дальше SenseDropRange, мёртвые и выгруженные её теряют. В отличие от чутья - не только нежить: звери, /// бандиты, зомби. Не метятся: тело игрока и другие игроки, питомцы мода (призрачные), торговцы. /// public static class DogSense { public const string DogClass = "necroZombieDog"; static readonly HashSet _sensed = new HashSet(); static float _check; public static bool Is(EntityAlive _e) { return _e != null && EntityClass.list.TryGetValue(_e.entityClass, out EntityClass cls) && cls != null && cls.entityClassName == DogClass; } static bool Smells(EntityAlive _e, EntityAlive _dog) { return _e != null && _e != _dog && !_e.IsDead() && !(_e is EntityPlayer) && !(_e is EntityTrader) && !SnakeControl.IsNecroEntity(_e) && !GhostTraderPatch.ShouldBeGhost(_e); } public static void Tick(World _world, EntityAlive _dog, float _dt) { _check -= _dt; if (_check > 0f) { return; } _check = 1f; Vector3 at = _dog.position; for (int i = 0; i < _world.EntityAlives.Count; i++) { EntityAlive e = _world.EntityAlives[i]; if (e == null) { continue; } float d2 = (e.position - at).sqrMagnitude; bool smell = Smells(e, _dog); if (smell && d2 < SnakeControl.SenseRange * SnakeControl.SenseRange) { if (_sensed.Add(e.entityId)) { e.AddNavObject(SnakeControl.SenseNavObject, null, null); } } else if (_sensed.Contains(e.entityId) && (!smell || d2 > SnakeControl.SenseDropRange * SnakeControl.SenseDropRange)) { e.RemoveNavObject(SnakeControl.SenseNavObject); _sensed.Remove(e.entityId); } } _sensed.RemoveWhere(id => _world.GetEntity(id) == null); } /// Выход из собаки - снять все метки. public static void Clear() { World world = GameManager.Instance?.World; if (world != null) { foreach (int id in _sensed) { (world.GetEntity(id) as EntityAlive)?.RemoveNavObject(SnakeControl.SenseNavObject); } } _sensed.Clear(); _check = 0f; } } }