public static AuraPreviewRecord getPreviewCache(this AbstractActor movingActor, Vector3 position)
        {
            int currentTurn  = movingActor.Combat.TurnDirector.CurrentRound;
            int currentPhase = movingActor.Combat.TurnDirector.CurrentPhase;

            if ((CAEAuraHelper.auraCachePhase != currentPhase) || (currentTurn != CAEAuraHelper.auraCacheTurn))
            {
                auraPreviewCache            = new Dictionary <AbstractActor, Dictionary <Vector3, AuraPreviewRecord> >();
                CAEAuraHelper.auraCacheTurn = currentTurn; auraCachePhase = currentPhase;
            }
            ;
            if (auraPreviewCache.ContainsKey(movingActor))
            {
                if (auraPreviewCache[movingActor].ContainsKey(position))
                {
                    return(auraPreviewCache[movingActor][position]);
                }
            }
            else
            {
                auraPreviewCache.Add(movingActor, new Dictionary <Vector3, AuraPreviewRecord>());
            }
            AuraPreviewRecord result = movingActor.fillPreviewCache(position);

            auraPreviewCache[movingActor].Add(position, result);
            return(result);
        }
        public static AuraPreviewRecord fillPreviewCache(this AbstractActor movingActor, Vector3 position)
        {
            AuraActorBody body = movingActor.bodyAura();

            if (body == null)
            {
                Log.WriteCritical("WARNING!" + movingActor.DisplayName + ":" + movingActor.GUID + " has no body to apply auras\n");
                return(new AuraPreviewRecord(movingActor));
            }
            HashSet <AuraBubble> newAuras = new HashSet <AuraBubble>();
            HashSet <AuraBubble> remAuras = new HashSet <AuraBubble>();

            foreach (var aura in body.affectedAurasEffects)
            {
                if (aura.Key.owner.GUID != movingActor.GUID)
                {
                    remAuras.Add(aura.Key);
                }
            }
            Collider[] hitColliders = Physics.OverlapSphere(position, 1f);
            foreach (Collider collider in hitColliders)
            {
                AuraBubble aura = collider.gameObject.GetComponent <AuraBubble>();
                if (aura == null)
                {
                    continue;
                }
                if (aura.Def.RemoveOnSensorLock && movingActor.IsSensorLocked)
                {
                    continue;
                }
                if (aura.owner.GUID == movingActor.GUID)
                {
                    continue;
                }
                if (body.affectedAurasEffects.ContainsKey(aura) == false)
                {
                    newAuras.Add(aura);
                }
                else
                {
                    remAuras.Remove(aura);
                }
            }
            AuraPreviewRecord result = new AuraPreviewRecord(movingActor);

            result.aurasAdded.Add(movingActor, new List <AuraPreview>());
            result.aurasRemoved.Add(movingActor, new List <AuraPreview>());
            List <AuraPreview> tmpList = result.aurasAdded[movingActor];

            foreach (AuraBubble aura in newAuras)
            {
                if ((aura.owner.GUID == movingActor.GUID) && (aura.Def.ApplySelf == false))
                {
                    continue;
                }
                tmpList.Add(new AuraPreview(aura.owner, movingActor, aura.Def));
            }
            tmpList = result.aurasRemoved[movingActor];
            foreach (AuraBubble aura in remAuras)
            {
                tmpList.Add(new AuraPreview(aura.owner, movingActor, aura.Def));
            }
            List <AuraBubble> actorAuras = movingActor.actorAuras();

            foreach (AuraBubble aura in actorAuras)
            {
                if (aura.collider.enabled == false)
                {
                    continue;
                }
                if (aura.collider.radius < 1f)
                {
                    continue;
                }
                hitColliders = Physics.OverlapSphere(position, aura.collider.radius);
                HashSet <AbstractActor> newUnits = new HashSet <AbstractActor>();
                HashSet <AbstractActor> remUnits = new HashSet <AbstractActor>();
                foreach (var unit in aura.affectedTo)
                {
                    if (unit.owner.GUID != movingActor.GUID)
                    {
                        remUnits.Add(unit.owner);
                    }
                }
                foreach (Collider collider in hitColliders)
                {
                    AuraActorBody otherBody = collider.gameObject.GetComponent <AuraActorBody>();
                    if (otherBody == null)
                    {
                        continue;
                    }
                    if (movingActor.GUID == otherBody.owner.GUID)
                    {
                        continue;
                    }
                    if (aura.Def.RemoveOnSensorLock && otherBody.owner.IsSensorLocked)
                    {
                        continue;
                    }
                    if (aura.affectedTo.Contains(otherBody) == false)
                    {
                        newUnits.Add(otherBody.owner);
                    }
                    else
                    {
                        remUnits.Remove(otherBody.owner);
                    }
                }
                foreach (AbstractActor unit in newUnits)
                {
                    if (result.aurasAdded.ContainsKey(unit) == false)
                    {
                        result.aurasAdded.Add(unit, new List <AuraPreview>());
                    }
                    ;
                    result.aurasAdded[unit].Add(new AuraPreview(aura.owner, unit, aura.Def));
                }
                foreach (AbstractActor unit in remUnits)
                {
                    if (result.aurasRemoved.ContainsKey(unit) == false)
                    {
                        result.aurasRemoved.Add(unit, new List <AuraPreview>());
                    }
                    ;
                    result.aurasRemoved[unit].Add(new AuraPreview(aura.owner, unit, aura.Def));
                }
            }
            result.RecalculateStealthPips();
            //Log.LogWrite("fillPreviewCache:"+movingActor.DisplayName+" "+position.ToString()+"\n");
            //result.DBGLogPrint();
            return(result);
        }