コード例 #1
0
    public override float CalculateDesirability(Agent agent, bool requested)
    {
        DesirabilitiesConfig desirabilitiesConfig = GameManager.Instance.DesirabilitiesConfig;

        DataNest dataNest = agent.Memory.Nests.Read().FirstOrDefault(data => data.nest.SpecieID == agent.Creature.SpecieID);

        if (dataNest == null)
        {
            return(0);
        }

        float distanceFromNest = Vector3.Distance(agent.transform.position, dataNest.nest.transform.position);

        if (distanceFromNest > desirabilitiesConfig.ReachNestConsiderationMaxDistance)
        {
            distanceFromNest = desirabilitiesConfig.ReachNestConsiderationMaxDistance;
        }

        float desirability = desirabilitiesConfig.ReachNestDesirabilityByDistance.Evaluate(distanceFromNest / desirabilitiesConfig.ReachNestConsiderationMaxDistance)
                             * desirabilitiesConfig.ReachNestDesirabilityTwicker;

        if (agent.Thinking.ActiveGoal?.GetType() == typeof(GoalEvade))
        {
            desirability *= desirabilitiesConfig.ReachNestConfirmationBias;
        }

        return(desirability);
    }
コード例 #2
0
    public override float CalculateDesirability(Agent agent, bool requested)
    {
        if (Player.Instance.IsDie)
        {
            return(0);
        }

        DesirabilitiesConfig desirabilitiesConfig = GameManager.Instance.DesirabilitiesConfig;

        if (agent.Creature.Traits.Vigilance.Value > desirabilitiesConfig.ObservePlayerConsiderationMaxVigilance)
        {
            return(0);
        }

        bool playerDetected = agent.Memory.Player.lastSeeTime > Time.time - 1f;

        if (!playerDetected)
        {
            return(0);
        }

        if (agent.Thinking.ActiveGoal?.GetType() == typeof(GoalEatInPlayerHand))
        {
            return(0);
        }

        if (agent.Thinking.ActiveGoal?.GetType() != typeof(GoalObservePlayer) &&
            agent.Memory.Player.lastObserved > Time.time - desirabilitiesConfig.ObservePlayerMinTimeRepeat)
        {
            return(0);
        }

        float distanceWithPlayer = Vector3.Distance(agent.transform.position, Player.Instance.transform.position);

        float desirability = desirabilitiesConfig.ObservePlayerDesirabilityByDistance.Evaluate(1 - distanceWithPlayer / desirabilitiesConfig.ObservePlayerConsiderationMaxDistance)
                             * desirabilitiesConfig.ObservePlayerDesirabilityByCuriosiry.Evaluate(agent.Creature.Traits.Curiosity.Value)
                             * desirabilitiesConfig.ObservePlayerDesirabilityByVigilance.Evaluate(agent.Creature.Traits.Vigilance.Value)
                             * desirabilitiesConfig.ObservePlayerDesirabilityTwicker;

        if (agent.Thinking.ActiveGoal?.GetType() == typeof(GoalObservePlayer))
        {
            desirability *= desirabilitiesConfig.ObservePlayerConfirmationBias;
        }

        if (GoalEatInPlayerHand_Evaluator.Instance.IsPlayerWantGiveFood())
        {
            desirability *= desirabilitiesConfig.ObservePlayerDesirabilityTwickerWithFoodHolder;
        }

        if (agent.Memory.Player.lastTimeFoodGive > Time.time - 10f)
        {
            desirability *= desirabilitiesConfig.ObservePlayerDesirabilityTwickerWithGiveFood;
        }

        return(desirability);
    }
コード例 #3
0
    public override float CalculateDesirability(Agent agent, bool requested)
    {
        DesirabilitiesConfig desirabilitiesConfig = GameManager.Instance.DesirabilitiesConfig;

        IReadOnlyCollection <DataCreature> creatures = agent.Memory.Creatures.Read();
        float    minDistanceFromHostil = -1;
        Creature closestHostil         = null;

        foreach (DataCreature data in creatures)
        {
            Agent otherAgent = data.creature?.agentCreature;
            if (!otherAgent || !otherAgent.gameObject.activeSelf || data.RegistrationDate < Time.time - 1f)
            {
                continue;
            }

            //bool attackSpecies = otherAgent.Steering.Target && otherAgent.Steering.Target.Creature.SpecieID == agent.Creature.SpecieID;
            //if(!attackSpecies) continue;

            if (otherAgent.Thinking.ActiveGoal?.GetType() == typeof(GoalTired))
            {
                return(0);
            }

            float distance = Vector3.Distance(agent.transform.position, otherAgent.transform.position);

            bool isHostil = GoalEvade.CreatureIsHostil(agent, otherAgent.Creature);
            if (!isHostil)
            {
                continue;
            }

            if (minDistanceFromHostil == -1 || distance < minDistanceFromHostil)
            {
                minDistanceFromHostil = distance;
                closestHostil         = otherAgent.Creature;
            }
        }

        if (minDistanceFromHostil == -1)
        {
            return(0);
        }

        float desirability = desirabilitiesConfig.DefenseDesirabilityByAggressivity.Evaluate(agent.Creature.Traits.Aggressivity.Value)
                             * desirabilitiesConfig.DefenseDesirabilityTwicker
                             * ForceEvaluation.Evaluate(agent, closestHostil);

        if (agent.Thinking.ActiveGoal?.GetType() == typeof(GoalDefense))
        {
            desirability *= desirabilitiesConfig.DefenseConfirmationBias;
        }

        return(desirability);
    }
コード例 #4
0
    public override float CalculateDesirability(Agent agent, bool requested)
    {
        //TODO TEMP
        if (agent.Creature.Traits.Carnivorous < 0.5f)
        {
            return(0);
        }
        if (agent.Steering.Behavior != eSteeringBehavior.Seek && agent.Steering.Behavior != eSteeringBehavior.Wander && agent.Thinking.ActiveGoal?.GetType() != typeof(GoalAvoidPrey))
        {
            return(0);
        }

        DesirabilitiesConfig desirabilitiesConfig = GameManager.Instance.DesirabilitiesConfig;

        List <int> preys = new List <int>(agent.Memory.Species.GetByKey(agent.Creature.SpecieID).CarnivorousFoods.Select(food => food.preyID));
        IReadOnlyCollection <DataCreature> creatures = agent.Memory.Creatures.Read();
        float    minDistanceFromPrey = -1;
        Creature closestPrey         = null;

        foreach (DataCreature data in creatures)
        {
            Agent otherAgent = data.creature?.agentCreature;
            if (!otherAgent || !agent.gameObject.activeSelf || data.RegistrationDate < Time.time - 2f)
            {
                continue;
            }

            float distance = Vector3.Distance(agent.transform.position, otherAgent.transform.position);

            bool isPrey = preys.Contains(otherAgent.Creature.SpecieID);
            if (isPrey && (minDistanceFromPrey == -1 || distance < minDistanceFromPrey))
            {
                minDistanceFromPrey = distance;
                closestPrey         = otherAgent.Creature;
            }
        }

        if (minDistanceFromPrey == -1)
        {
            return(0);
        }

        float desirability = desirabilitiesConfig.AvoidPreyDesirabilityByDistance.Evaluate(1 - minDistanceFromPrey / desirabilitiesConfig.AvoidPreyConsiderationMaxDistance)
                             * desirabilitiesConfig.AvoidPreyDesirabilityTwicker
                             * (1 / ForceEvaluation.Evaluate(agent, closestPrey));

        if (agent.Thinking.ActiveGoal?.GetType() == typeof(GoalAvoidPrey))
        {
            desirability *= desirabilitiesConfig.AvoidPreyConfirmationBias;
        }

        return(desirability);
    }
コード例 #5
0
    public override void Process()
    {
        Goal child = GetActiveGoal();

        if (child.IsInactive)
        {
            child.Activate();
        }

        DesirabilitiesConfig desirabilitiesConfig = GameManager.Instance.DesirabilitiesConfig;

        float vigilanceConsideration = desirabilitiesConfig.DefensePlayerConsiderationMinVigilance;

        float vigilance     = desirabilitiesConfig.DefensePlayerDesirabilityByAggressivity.Evaluate(owner.Creature.Traits.Vigilance.Value) * (1 / vigilanceConsideration);
        float distToObserve = Mathf.Lerp(minDistToObserve, maxDistToObserve, 1 - vigilance);

        bool playerClose = owner.Memory.Player.lastSeeTime > Time.time - 1f &&
                           Vector3.Distance(owner.transform.position, Player.Instance.transform.position) < distToObserve;

        switch (evadeState)
        {
        case ObserveState.Pursuit:
            if (child.IsComplete)
            {
                AddSubgoal(new GoalLookAtPlayer(owner));
                evadeState = ObserveState.LookAt;
            }
            else if (playerClose)
            {
                child.Abort();
                AddSubgoal(new GoalLookAtPlayer(owner));
                evadeState = ObserveState.LookAt;
            }
            break;

        case ObserveState.LookAt:
            if (!playerClose)
            {
                child.Abort();
                AddSubgoal(new GoalPursuitPlayer(owner));
                evadeState = ObserveState.Pursuit;
            }
            break;
        }

        if (Time.time - timeStart >= desirabilitiesConfig.ObservePlayerMaxTimeSpend)
        {
            status = GoalStatus.Completed;
        }

        base.ProcessSubgoals();
    }
コード例 #6
0
    public override float CalculateDesirability(Agent agent, bool requested)
    {
        DesirabilitiesConfig desirabilitiesConfig = GameManager.Instance.DesirabilitiesConfig;

        float desirability = desirabilitiesConfig.HungryDesirabilityByStomack.Evaluate(1 - agent.Creature.Gauges.Hunger.Rate)
                             * desirabilitiesConfig.HungryDesirabilityByGluttony.Evaluate(agent.Creature.Traits.Gluttony.Value)
                             * desirabilitiesConfig.HungryDesirabilityTwicker;

        if (agent.Thinking.ActiveGoal?.GetType() == typeof(GoalHungry))
        {
            desirability *= desirabilitiesConfig.HungryConfirmationBias;
        }
        return(desirability);
    }
コード例 #7
0
    public override float CalculateDesirability(Agent agent, bool requested)
    {
        //TODO TEMP
        if (agent.Creature.Traits.Carnivorous >= 0.5f)
        {
            return(0);
        }

        DesirabilitiesConfig desirabilitiesConfig = GameManager.Instance.DesirabilitiesConfig;

        IReadOnlyCollection <DataCreature> creatures = agent.Memory.Creatures.Read();
        float    minDistanceFromHostil = -1;
        Creature closestHostil         = null;

        foreach (DataCreature data in creatures)
        {
            Agent otherAgent = data.creature?.agentCreature;
            if (!otherAgent || !agent.gameObject.activeSelf || data.RegistrationDate < Time.time - 2f)
            {
                continue;
            }

            float distance = Vector3.Distance(agent.transform.position, otherAgent.transform.position);

            bool isHostil = GoalEvade.CreatureIsHostil(agent, otherAgent.Creature);
            if (isHostil && (minDistanceFromHostil == -1 || distance < minDistanceFromHostil))
            {
                minDistanceFromHostil = distance;
                closestHostil         = otherAgent.Creature;
            }
        }

        if (minDistanceFromHostil == -1)
        {
            return(0);
        }

        float desirability = desirabilitiesConfig.EvadeDesirabilityByDistance.Evaluate(1 - minDistanceFromHostil / desirabilitiesConfig.EvadeConsiderationMaxDistance)
                             * desirabilitiesConfig.EvadeDesirabilityByAggressivity.Evaluate(agent.Creature.Traits.Aggressivity.Value)
                             * desirabilitiesConfig.EvadeDesirabilityTwicker
                             * (1 / ForceEvaluation.Evaluate(agent, closestHostil));

        if (agent.Thinking.ActiveGoal?.GetType() == typeof(GoalEvade))
        {
            desirability *= desirabilitiesConfig.EvadeConfirmationBias;
        }

        return(desirability);
    }
コード例 #8
0
    public override float CalculateDesirability(Agent agent, bool requested)
    {
        DesirabilitiesConfig desirabilitiesConfig = GameManager.Instance.DesirabilitiesConfig;

        //float sleepDistance = Mathf.Abs((DayCycleManager.Instance.Cycle + 0.5f) % 1 - agent.Creature.Traits.Nocturnal.Value);
        float sleep = Mathf.Abs(((DayCycleManager.Instance.Cycle + agent.Creature.Traits.Nocturnal.Value) % 1) * 2 - 1);

        float desirability = desirabilitiesConfig.SleepDesirabilityByCycleTime.Evaluate(sleep)
                             * desirabilitiesConfig.SleepDesirabilityTwicker;

        if (agent.Thinking.ActiveGoal?.GetType() == typeof(GoalTired))
        {
            desirability *= desirabilitiesConfig.SleepConfirmationBias;
        }

        return(desirability);
    }
コード例 #9
0
    public static bool CreatureIsHostil(Agent owner, Creature other)
    {
        if (owner.Creature.SpecieID == other.SpecieID)
        {
            return(false);
        }

        DataSpecies data = owner.Memory.Species.GetByKey(other.SpecieID);

        if (data == null)
        {
            return(false);
        }
        if (owner.Debug)
        {
            /*Debug.Log("List : " + other.SpecieID);
             * foreach(int i in data.preyIDs){
             *  Debug.Log("i");
             * }*/
        }

        bool isEatMe = data.IsCarnivorous && data.PreyIDs.Contains(owner.Creature.SpecieID);

        if (other.agentCreature.IsThinking)
        {
            if (!isEatMe)
            {
                return(false);
            }
        }
        else
        {
            if (!isEatMe && (other.agentCreature.Steering.Target == null || other.agentCreature.Steering.Target.Creature.SpecieID != owner.Creature.SpecieID))
            {
                return(false);
            }
        }

        //if(other.Traits.Carnivorous.Value < 0.5f) return false;

        DesirabilitiesConfig desirabilitiesConfig = GameManager.Instance.DesirabilitiesConfig;

        return(Vector3.Distance(owner.transform.position, other.transform.position) < desirabilitiesConfig.EvadeConsiderationMaxDistance / 2);
    }
コード例 #10
0
    public override float CalculateDesirability(Agent agent, bool requested)
    {
        if (agent.Creature.Age < 0.4f)
        {
            return(0);
        }

        //TODO temporaire, pour éviter la surpopulation :

        /*if(SpeciesMetrics.Instance && SpeciesMetrics.Instance.IsReady){
         *  int nbCreatures = SpeciesMetrics.Instance.NbCreatures[agent.Creature.SpecieID];
         *  if(nbCreatures >= 18){
         *      return 0;
         *  }
         * }*/

        int nbCreatures = CreatureFactory.Instance.AliveCreature.Count(c => c.SpecieID == agent.Creature.SpecieID);

        if (nbCreatures >= 18)
        {
            return(0);
        }

        DesirabilitiesConfig desirabilitiesConfig = GameManager.Instance.DesirabilitiesConfig;

        float desirability = desirabilitiesConfig.ReproductionDesirabilityByTimer.Evaluate(1 - agent.Creature.Gauges.Reproduction.Rate)
                             * desirabilitiesConfig.ReproductionDesirabilityByLust.Evaluate(agent.Creature.Traits.Lust.Value)
                             * desirabilitiesConfig.ReproductionDesirabilityTwicker;

        if (agent.Thinking.ActiveGoal?.GetType() == typeof(GoalReproduction) ||
            agent.Thinking.ActiveGoal?.GetType() == typeof(GoalReproduce))
        {
            desirability *= desirabilitiesConfig.ReproductionConfirmationBias;
        }
        if (requested)
        {
            desirability *= desirabilitiesConfig.ReproductionRequestBias;
        }

        return(desirability);
    }
コード例 #11
0
    public override float CalculateDesirability(Agent agent, bool requested)
    {
        if (Player.Instance.IsDie)
        {
            return(0);
        }

        DesirabilitiesConfig desirabilitiesConfig = GameManager.Instance.DesirabilitiesConfig;

        if (agent.Creature.Traits.Vigilance.Value < desirabilitiesConfig.EvadePlayerConsiderationMinVigilance)
        {
            return(0);
        }

        bool playerDetected = agent.Memory.Player.lastSeeTime > Time.time - 2f;

        if (!playerDetected)
        {
            return(0);
        }

        float distanceWithPlayer = Vector3.Distance(agent.transform.position, Player.Instance.transform.position);

        float desirability = desirabilitiesConfig.EvadePlayerDesirabilityByDistance.Evaluate(1 - distanceWithPlayer / desirabilitiesConfig.EvadePlayerConsiderationMaxDistance)
                             * desirabilitiesConfig.EvadePlayerDesirabilityByAggressivity.Evaluate(agent.Creature.Traits.Aggressivity.Value)
                             * desirabilitiesConfig.EvadePlayerDesirabilityByVigilance.Evaluate(agent.Creature.Traits.Vigilance.Value)
                             * desirabilitiesConfig.EvadePlayerDesirabilityTwicker
                             * (1 / ForceEvaluation.EvaluateAgainstPlayer(agent));

        if (agent.Thinking.ActiveGoal?.GetType() == typeof(GoalEvadePlayer))
        {
            desirability *= desirabilitiesConfig.EvadePlayerConfirmationBias;
        }

        if (GoalEatInPlayerHand_Evaluator.Instance.IsPlayerWantGiveFood())
        {
            desirability *= desirabilitiesConfig.EvadePlayerDesirabilityTwickerWithFoodHolder;
        }

        return(desirability);
    }
コード例 #12
0
    public override float CalculateDesirability(Agent agent, bool requested)
    {
        if (agent.Creature.Traits.Carnivorous > 0.5f)
        {
            return(0);
        }
        if (Player.Instance.IsDie)
        {
            return(0);
        }
        if (!IsPlayerWantGiveFood())
        {
            return(0);
        }

        DesirabilitiesConfig desirabilitiesConfig = GameManager.Instance.DesirabilitiesConfig;

        bool playerDetected = agent.Memory.Player.lastSeeTime > Time.time - 2f;

        if (!playerDetected)
        {
            return(0);
        }

        float distanceWithPlayer = Vector3.Distance(agent.transform.position, Player.Instance.transform.position);

        float desirability = GoalHungry_Evaluator.Instance.CalculateDesirability(agent, requested)
                             * desirabilitiesConfig.EatInPlayerHandDesirabilityByAggressivity.Evaluate(agent.Creature.Traits.Aggressivity.Value)
                             * desirabilitiesConfig.EatInPlayerHandDesirabilityByVigilance.Evaluate(agent.Creature.Traits.Vigilance.Value)
                             * desirabilitiesConfig.EatInPlayerHandDesirabilityTwicker;

        if (agent.Thinking.ActiveGoal?.GetType() == typeof(GoalEatInPlayerHand))
        {
            desirability *= desirabilitiesConfig.EatInPlayerHandConfirmationBias;
        }

        return(desirability);
    }
コード例 #13
0
    public override float CalculateDesirability(Agent agent, bool requested)
    {
        if (!agent.Creature.MetabolismActive)
        {
            return(0);
        }

        DesirabilitiesConfig desirabilitiesConfig = GameManager.Instance.DesirabilitiesConfig;

        float lastComTime = desirabilitiesConfig.CommunicationConsiderationMaxTime;
        IReadOnlyCollection <DataCommunication> communications = agent.Memory.Communications.Read();

        foreach (DataCommunication com in communications)
        {
            float time = Time.time - com.RegistrationDate;
            if (time < lastComTime)
            {
                lastComTime = time;
            }
        }

        float desirability = desirabilitiesConfig.CommunicationDesirabilityByTime.Evaluate(lastComTime / desirabilitiesConfig.CommunicationConsiderationMaxTime)
                             * desirabilitiesConfig.CommunicationDesirabilityBySociability.Evaluate(agent.Creature.Traits.Sociability.Value)
                             * desirabilitiesConfig.CommunicationDesirabilityTwicker;

        if (agent.Thinking.ActiveGoal?.GetType() == typeof(GoalCommunication) ||
            agent.Thinking.ActiveGoal?.GetType() == typeof(GoalShare))
        {
            desirability *= desirabilitiesConfig.CommunicationConfirmationBias;
        }
        if (requested)
        {
            desirability *= desirabilitiesConfig.CommunicationRequestBias;
        }

        return(desirability);
    }
コード例 #14
0
    public override void Activate()
    {
        base.Activate();

        DataNest dataNest = owner.Memory.Nests.Read().FirstOrDefault(data => data.nest.SpecieID == owner.Creature.SpecieID);

        if (dataNest == null)
        {
            status = GoalStatus.Failed;
            return;
        }

        DesirabilitiesConfig desirabilitiesConfig = GameManager.Instance.DesirabilitiesConfig;

        float distWithNest = dataNest != null?Vector3.Distance(owner.transform.position, dataNest.nest.transform.position) : 0;

        float wantDistWithNest = desirabilitiesConfig.SlepConsiderationMinNestDistance + (desirabilitiesConfig.SlepConsiderationMaxNestDistance - desirabilitiesConfig.SlepConsiderationMinNestDistance)
                                 * desirabilitiesConfig.SleepToNestDesirabilityBySociability.Evaluate(owner.Creature.Traits.Sociability.Value);

        wantDistWithNest = Random.Range(desirabilitiesConfig.SlepConsiderationMinNestDistance, wantDistWithNest);
        Vector2 randPos = Random.insideUnitCircle;

        AddSubgoal(new GoalSeek(owner, dataNest.nest.transform.position + new Vector3(randPos.x, 0, randPos.y) * wantDistWithNest));
    }
コード例 #15
0
    public override float CalculateDesirability(Agent agent, bool requested)
    {
        if (Player.Instance.IsDie)
        {
            return(0);
        }

        DesirabilitiesConfig desirabilitiesConfig = GameManager.Instance.DesirabilitiesConfig;

        if (agent.Creature.Traits.Vigilance.Value > desirabilitiesConfig.ProtectPlayerConsiderationMaxVigilance)
        {
            return(0);
        }

        bool playerDetected = agent.Memory.Player.lastSeeTime > Time.time - 1f;

        if (!playerDetected)
        {
            return(0);
        }

        IReadOnlyCollection <DataCreature> creatures = agent.Memory.Creatures.Read();
        float    minDistanceFromHostil = -1;
        Creature closestHostil         = null;

        foreach (DataCreature data in creatures)
        {
            Agent otherAgent = data.creature?.agentCreature;
            if (!otherAgent || !otherAgent.gameObject.activeSelf || data.RegistrationDate < Time.time - 1f)
            {
                continue;
            }

            if (otherAgent.Creature.SpecieID == agent.Creature.SpecieID)
            {
                continue;
            }

            if (otherAgent.Thinking.ActiveGoal?.GetType() == typeof(GoalTired))
            {
                continue;
            }

            Goal goal = otherAgent.Thinking.ActiveGoal;
            if (!(goal is GoalDefensePlayer))
            {
                continue;
            }

            Goal subGoal = (goal as GoalComposite).GetActiveGoal();
            if (subGoal == null || (!(subGoal is GoalPursuitPlayer) && !(subGoal is GoalAttackPlayer)))
            {
                continue;
            }

            float distance = Vector3.Distance(agent.transform.position, otherAgent.transform.position);

            if (minDistanceFromHostil == -1 || distance < minDistanceFromHostil)
            {
                minDistanceFromHostil = distance;
                closestHostil         = otherAgent.Creature;
            }
        }

        if (minDistanceFromHostil == -1)
        {
            return(0);
        }

        float desirability = desirabilitiesConfig.ProtectPlayerDesirabilityByAggressivity.Evaluate(agent.Creature.Traits.Aggressivity.Value)
                             * desirabilitiesConfig.ProtectPlayerDesirabilityByVigilance.Evaluate(agent.Creature.Traits.Vigilance.Value)
                             * desirabilitiesConfig.ProtectPlayerDesirabilityTwicker
                             * ForceEvaluation.Evaluate(agent, closestHostil);

        if (agent.Thinking.ActiveGoal?.GetType() == typeof(GoalProtectPlayer))
        {
            desirability *= desirabilitiesConfig.ProtectPlayerConfirmationBias;
        }

        return(desirability);
    }
コード例 #16
0
    public override void Process()
    {
        DesirabilitiesConfig desirabilitiesConfig = GameManager.Instance.DesirabilitiesConfig;

        float vigilanceConsideration = desirabilitiesConfig.DefensePlayerConsiderationMinVigilance;

        float vigilance = (desirabilitiesConfig.DefensePlayerDesirabilityByAggressivity.Evaluate(owner.Creature.Traits.Vigilance.Value) - vigilanceConsideration) * (1 / (1 - vigilanceConsideration));

        vigilance *= (Player.Instance.PlayerController.Velocity.magnitude * desirabilitiesConfig.DefensePlayerPlayerSpeedThreatWeight);
        float distToAttack  = Mathf.Lerp(minDistToAttack, maxDistToAttack, vigilance);
        float distToPursuit = Mathf.Lerp(minDistToPursuit, maxDistToPursuit, vigilance);

        Vector3 playerPos        = Player.Instance.transform.position;
        float   distanceToPlayer = Vector3.Distance(owner.transform.position, playerPos);

        Goal child = GetActiveGoal();

        if (child != null && child.IsInactive)
        {
            child.Activate();
        }

        switch (defenseState)
        {
        case DefenseState.LookAt:

            if (owner.Steering.Behavior != eSteeringBehavior.LookAtPlayer)
            {
                AddSubgoal(new GoalLookAtPlayer(owner));
            }
            else if (distanceToPlayer < 2)
            {
                if (child != null)
                {
                    child.Abort();
                }
                AddSubgoal(new GoalAttackPlayer(owner));
                defenseState = DefenseState.Attack;
                timeStart    = Time.time;
            }
            else if (Time.time - timeStart >= desirabilitiesConfig.DefensePlayerMaxTimeSpend)
            {
                status = GoalStatus.Completed;
            }
            else
            {
                IReadOnlyCollection <DataCreature> friends = owner.Memory.Creatures.Read();
                bool  friendAggresed = false;
                Agent friend         = null;
                foreach (DataCreature data in friends)
                {
                    if (!data.creature)
                    {
                        continue;
                    }
                    Agent agent = data.creature.agentCreature;

                    if (!agent.gameObject.activeSelf || data.RegistrationDate < Time.time - 1f)
                    {
                        continue;
                    }

                    if (Vector3.Distance(agent.transform.position, playerPos) < distToAttack)
                    {
                        friendAggresed = true;
                        friend         = agent;
                        break;
                    }
                }

                if (!friendAggresed)
                {
                    friendAggresed = Vector3.Distance(owner.transform.position, playerPos) < distToAttack;
                    friend         = owner;
                }

                if (friendAggresed)
                {
                    if (child != null)
                    {
                        child.Abort();
                    }
                    AddSubgoal(new GoalPursuitPlayer(owner));
                    defenseState = DefenseState.Pursuit;
                    if (Random.value > 0.5f)
                    {
                        owner.Creature.AudioBox.PlayOneShot(SoundOneShot.CreatureDefense);
                    }
                    timeStart = Time.time;
                }
            }
            break;

        case DefenseState.Pursuit:
            if (child.IsComplete)
            {
                AddSubgoal(new GoalAttackPlayer(owner));
                defenseState = DefenseState.Attack;
            }
            else if (child.HasFailed)
            {
                defenseState = DefenseState.LookAt;
            }
            else if (Vector3.Distance(owner.transform.position, playerPos) > distToPursuit)
            {
                child.Abort();
                defenseState = DefenseState.LookAt;
            }
            break;

        case DefenseState.Attack:
            if (child.IsComplete || child.HasFailed)
            {
                IReadOnlyCollection <DataCreature> friends = owner.Memory.Creatures.Read();
                bool  friendAggresed = false;
                Agent friend         = null;
                foreach (DataCreature data in friends)
                {
                    if (!data.creature)
                    {
                        continue;
                    }
                    Agent agent = data.creature.agentCreature;

                    if (!agent.gameObject.activeSelf || data.RegistrationDate < Time.time - 1f)
                    {
                        continue;
                    }

                    if (Vector3.Distance(agent.transform.position, playerPos) < distToAttack)
                    {
                        friendAggresed = true;
                        friend         = agent;
                        break;
                    }
                }

                if (!friendAggresed)
                {
                    friendAggresed = Vector3.Distance(owner.transform.position, playerPos) < distToAttack;
                    friend         = owner;
                }

                if (friendAggresed)
                {
                    if (child != null)
                    {
                        child.Abort();
                    }
                    AddSubgoal(new GoalPursuitPlayer(owner));
                    defenseState = DefenseState.Pursuit;
                }
                else
                {
                    AddSubgoal(new GoalLookAtPlayer(owner));
                    defenseState = DefenseState.LookAt;
                }
            }
            break;
        }

        base.ProcessSubgoals();
    }