public AIState?StateUpdate()
        {
            if (!_agent.IsAlive())
            {
                return(_fallbackState);
            }

            if (!_agent.HasTarget())
            {
                return(_fallbackState);
            }

            if (!_agent.IsBetweenFearAndAggro())
            {
                return(_fallbackState);
            }

            var distance = _agent.GetLineDistanceToTarget();

            if (distance < _desiredRange)
            {
                return(_nextState);
            }

            var direction = (_agent.ActiveTarget.transform.position - _agent.Transform.position).normalized;

            var moveTo = _agent.ActiveTarget.transform.position - direction * (_desiredRange - 0.1f);

            _agent.Movement.ControlSetDestination(moveTo);
            _agent.Movement.ControlLookAt(moveTo);

            return(null);
        }
Esempio n. 2
0
        public AIState?StateUpdate()
        {
            if (!_agent.IsAlive())
            {
                return(_fallbackState);
            }

            if (!_agent.HasTarget())
            {
                return(_fallbackState);
            }

            if (!_agent.IsBetweenFearAndAggro())
            {
                return(_fallbackState);
            }

            if (!_agent.CanCast())
            {
                return(_fallbackState);
            }

            // If no intentions to choose from -> fallback
            if (_agent.Config.AI.SlotConfig == null || _agent.Config.AI.SlotConfig.Length == 0)
            {
                return(_fallbackState);
            }

            // Select a slot to cast that is ready;
            var readySlots = _agent.Config.AI.SlotConfig.Where(s =>
            {
                var slotState = _agent.SpellBook.GetSpellSlotState(s.Slot);
                return(slotState.State == SpellbookState.SlotState.Ready);
            }).ToList();

            // Find and randomly choose an active slot
            if (readySlots.Count >= 0)
            {
                var intention = RandomUtils.Choice(readySlots, s => s.Weight);
                _agent.IntendedSpell = intention;
                return(_nextState);
            }

            // No slots to cast
            _agent.Logger.Log("No active slots to cast");
            return(_fallbackState);
        }
        public AIState?StateUpdate()
        {
            if (!_agent.IsAlive())
            {
                return(_outOfAggroRangeState);
            }

            if (!_agent.HasTarget())
            {
                return(_outOfAggroRangeState);
            }

            // Distance and direction
            var direction = _agent.ActiveTarget.transform.position - _agent.Transform.position;
            var distance  = (direction).magnitude;

            direction = direction.normalized;

            // We are too far from target
            if (distance > _agent.Config.AI.AggroRange)
            {
                return(_outOfAggroRangeState);
            }

            Vector3 targetPosition;

            switch (_moveMode)
            {
            case MoveMode.Inside:
                if (distance < _targetRange && distance < _agent.Config.AI.AggroRange)
                {
                    return(_inRangeState);
                }
                targetPosition = _agent.ActiveTarget.transform.position - direction * (_targetRange - 0.1f);
                break;

            case MoveMode.Outside:
                if (distance > _targetRange && distance < _agent.Config.AI.AggroRange)
                {
                    return(_inRangeState);
                }
                targetPosition = _agent.ActiveTarget.transform.position - direction * (_targetRange + 0.1f);
                break;

            case MoveMode.Edge:
                if (Mathf.Abs(distance - _targetRange) < _edgeTolerance && distance < _agent.Config.AI.AggroRange)
                {
                    return(_inRangeState);
                }
                targetPosition = _agent.ActiveTarget.transform.position - direction * _targetRange;
                break;

            default:
                targetPosition = _agent.ActiveTarget.transform.position - direction * _targetRange;
                break;
            }

            // Do actual movement
            _agent.Movement.ControlSetDestination(targetPosition);
            _agent.Movement.ControlLookAt(targetPosition);

            // Return same state
            return(null);
        }
Esempio n. 4
0
        public AIState?StateUpdate()
        {
            if (!_agent.IsAlive())
            {
                AbortIfCasting();
                return(_fallbackState);
            }

            if (!_agent.HasTarget())
            {
                AbortIfCasting();
                return(_fallbackState);
            }

            if (!_agent.IsBetweenFearAndAggro())
            {
                AbortIfCasting();
                return(_fallbackState);
            }

            if (_agent.IntendedSpell == null)
            {
                AbortIfCasting();
                return(_fallbackState);
            }

            var slotState = _agent.SpellBook.GetSpellSlotState(_agent.IntendedSpell.Slot);

            if (slotState.State == SpellbookState.SlotState.Ready)
            {
                if (_isCasting)
                {
                    // If we are casting and ended up in ready state
                    // then it means that the cast is completed
                    _agent.LastSpellCastTime = Time.time;
                    return(_nextState);
                }

                // If AI is not casting and the slot is ready
                // Cast the spell
                _agent.Movement.ControlLookAt(_agent.ActiveTarget.transform.position);
                _agent.Movement.ControlStop();

                if (_agent.SpellBook.TryFireSpellToTarget(_agent.IntendedSpell.Slot,
                                                          GetTarget(slotState.Spell.TargetType)))
                {
                    _isCasting = true;
                    return(null);
                }

                // Casting failed, fallback
                return(_fallbackState);
            }
            else if (slotState.State == SpellbookState.SlotState.Firing ||
                     slotState.State == SpellbookState.SlotState.Preparing)
            {
                // Update target while casting
                _targetProxy.Location = _agent.ActiveTarget.transform.position;

                // We are casting, we cool
                return(null);
            }

            // Failed to cast
            return(_fallbackState);
        }