Ejemplo n.º 1
0
        private void onActionSelected(object value)
        {
            var actions = (AIActions)target;

            Undo.RecordObject(actions, "Edit actions");

            if (actions.Actions == null)
            {
                actions.Actions = new AIAction[1];
            }
            else
            {
                var new_ = new AIAction[actions.Actions.Length + 1];
                for (int i = 0; i < new_.Length - 1; i++)
                {
                    new_[i] = actions.Actions[i];
                }
                actions.Actions = new_;
            }

            actions.Actions[actions.Actions.Length - 1] = (AIAction)CreateInstance(((Type)value).FullName);

            EditorUtility.SetDirty(actions);
            EditorSceneManager.MarkSceneDirty(UnityEngine.SceneManagement.SceneManager.GetActiveScene());
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Executes the given action targeted at an actor. Does not necessarily have to belong to the Actions list.
        /// </summary>
        public void Execute(AIAction action, Actor target)
        {
            if (_active != null || action.Wait > float.Epsilon)
            {
                return;
            }

            if (action.Execute(_actor, target))
            {
                begin(action);
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Executes the given action targeted at a position. Does not necessarily have to belong to the Actions list.
        /// </summary>
        public void Execute(AIAction action, Vector3 position)
        {
            if (_active != null || action.Wait > float.Epsilon)
            {
                return;
            }

            if (action.Execute(_actor, position))
            {
                begin(action);
            }
        }
Ejemplo n.º 4
0
 /// <summary>
 /// UI will ask the player to assign the target for the given action.
 /// </summary>
 public void GiveCommand(AIAction action)
 {
     _forcedAction = action;
 }
Ejemplo n.º 5
0
        private void Update()
        {
            if ((Disabler != null && Disabler.activeSelf) || EventSystem.current.IsPointerOverGameObject())
            {
                hideMarker();
                hideOutline(ref _targetOutline);
                hideSphere();

                if (Target == null)
                {
                    hideOutline(ref _performerOutline);
                }
                else
                {
                    showOutline(ref _performerOutline, Target, SelectColor);
                }

                return;
            }

            var camera = _camera;

            if (camera == null)
            {
                camera = Camera.main;
            }
            if (camera == null)
            {
                return;
            }

            var mouse = Input.mousePosition;

            mouse.z = camera.nearClipPlane;

            var near = camera.ScreenToWorldPoint(mouse);

            mouse.z = camera.farClipPlane;
            var far = camera.ScreenToWorldPoint(mouse);

            var hit         = Util.GetClosestNonActorHit(near, far, 1);
            var targetActor = AIUtil.FindClosestActorIncludingDead(hit, 0.7f);

            var isMouseDown = Input.GetMouseButtonDown(0);

            if (Target == null)
            {
                if (targetActor != null && targetActor.Side == Side && targetActor.IsAlive)
                {
                    showOutline(ref _performerOutline, targetActor, PickColor);

                    if (isMouseDown)
                    {
                        Target      = targetActor;
                        isMouseDown = false;
                    }
                }
                else
                {
                    hideOutline(ref _performerOutline);
                }
            }
            else if (Target != null)
            {
                showOutline(ref _performerOutline, Target, SelectColor);
            }
            else
            {
                hideOutline(ref _performerOutline);
            }

            AIActions targetActions = null;

            if (Target != null)
            {
                targetActions = Target.GetComponent <AIActions>();
            }

            if (targetActions)
            {
                var target = hit;
                AIUtil.GetClosestStandablePosition(ref target);

                var isActor    = targetActor != null;
                var isSelf     = isActor && targetActor == Target;
                var isAlly     = isActor && targetActor.Side == Target.Side;
                var isEnemy    = isActor && targetActor.Side != Target.Side;
                var isDead     = isActor && !targetActor.IsAlive;
                var isLocation = Vector3.Distance(target, hit) < 0.5f;

                AIAction action           = null;
                var      isTargetingActor = false;

                if (_forcedAction != null)
                {
                    if (_forcedAction.CanTargetGround && isLocation)
                    {
                        action = _forcedAction;
                    }
                    else if ((!isDead || !_forcedAction.ShouldIgnoreDead) &&
                             ((isSelf && _forcedAction.CanTargetSelf) ||
                              (isAlly && _forcedAction.CanTargetAlly) ||
                              (isEnemy && _forcedAction.CanTargetEnemy)))
                    {
                        action           = _forcedAction;
                        isTargetingActor = true;
                    }
                }
                else
                {
                    for (int i = 0; i < targetActions.Actions.Length; i++)
                    {
                        var a = targetActions.Actions[i];

                        if (a.CanTargetGround && isLocation)
                        {
                            action = a;
                            break;
                        }
                        else if ((!isDead || !a.ShouldIgnoreDead) &&
                                 ((isSelf && a.CanTargetSelf) ||
                                  (isAlly && a.CanTargetAlly) ||
                                  (isEnemy && a.CanTargetEnemy)))
                        {
                            action           = a;
                            isTargetingActor = true;
                            break;
                        }
                    }
                }

                if (action != null)
                {
                    if (isTargetingActor)
                    {
                        if (isSelf)
                        {
                            hideOutline(ref _performerOutline);
                        }

                        showOutline(ref _targetOutline, targetActor, action.UIColor);
                        hideMarker();
                        hideSphere();
                    }
                    else
                    {
                        if (action.UIRadius > 0.001f)
                        {
                            showSphere(target, action.UIColor, action.UIRadius);
                            hideOutline(ref _targetOutline);
                            hideMarker();
                        }
                        else
                        {
                            showMarker(target, action.UIColor);
                            hideOutline(ref _targetOutline);
                            hideSphere();
                        }
                    }
                }

                if (isMouseDown)
                {
                    isMouseDown = false;

                    if (action != null)
                    {
                        if (action.CanTargetGround)
                        {
                            targetActions.Execute(action, target);
                        }
                        else
                        {
                            targetActions.Execute(action, targetActor);
                        }

                        if (_forcedAction != null)
                        {
                            _forcedAction = null;
                        }
                    }

                    Target = null;
                }
                else if (Input.GetMouseButtonDown(1))
                {
                    Target = null;
                }
            }
            else
            {
                hideOutline(ref _targetOutline);
                hideMarker();
                hideSphere();
            }
        }
Ejemplo n.º 6
0
        private void Update()
        {
            if (_autoWait > float.Epsilon)
            {
                _autoWait -= Time.deltaTime;
            }
            if (_checkWait > float.Epsilon)
            {
                _checkWait -= Time.deltaTime;
            }
            if (_coverTimer > float.Epsilon)
            {
                _coverTimer -= Time.deltaTime;
            }

            if (_active != null && (!_active.Update() || (!_active.HasNoTimeout && (Time.timeSinceLevelLoad - _actionStart) > Timeout)))
            {
                end();
            }

            if (_actor.Cover == null)
            {
                _isInCover  = false;
                _coverTimer = 0;
            }
            else if (!_isInCover)
            {
                _coverTimer = CoverDelay;
                _isInCover  = true;
            }

            if (_active == null &&
                _autoWait <= float.Epsilon &&
                _checkWait <= float.Epsilon &&
                _brain.enabled &&
                _brain.State != FighterState.process &&
                _actor.IsAlive &&
                _coverTimer <= float.Epsilon &&
                (!WaitForCoverActions || !_isTakingCover))
            {
                _checkWait = 0.5f;
                _nearbyActors.Clear();

                {
                    var count = AIUtil.FindActorsIncludingDead(transform.position, AutoDistance);
                    for (int i = 0; i < count; i++)
                    {
                        _nearbyActors.Add(AIUtil.Actors[i]);
                    }
                }

                var canUseAttackAction = !AutoAttackOnlyFromCover || _actor.Cover != null;

                AIAction bestSingleAction       = null;
                Actor    bestSingleActionTarget = null;

                ///////////////////////////////////////////////////////
                //
                // CONSIDER MULTIPLE TARGET ACTIONS
                //
                ///////////////////////////////////////////////////////

                AIAction bestMultipleAction            = null;
                int      bestMultipleActionTargetCount = 0;

                for (int i = 0; i < Actions.Length; i++)
                {
                    var action = Actions[i];
                    if (action.Wait > float.Epsilon || !action.Auto || action.NeedsSingleTargetActor || action.NeedsTargetLocation || action.NeedsOnlySelf)
                    {
                        continue;
                    }

                    int count = 0;

                    for (int j = 0; j < Actors.Count; j++)
                    {
                        var actor = Actors.Get(j);

                        if (!actor.IsAlive && action.ShouldIgnoreDead)
                        {
                            continue;
                        }

                        if (actor.Side == _actor.Side)
                        {
                            if (((actor == _actor && action.CanTargetSelf) || action.CanTargetAlly) && action.IsNeededFor(actor))
                            {
                                count++;
                            }
                        }
                        else if (canUseAttackAction && action.CanTargetEnemy && action.IsNeededFor(actor) && (!AutoAttackOnlyFromCover || !action.WillMoveForActor(actor)))
                        {
                            count++;
                        }
                    }

                    if (count > bestMultipleActionTargetCount)
                    {
                        bestMultipleAction            = action;
                        bestMultipleActionTargetCount = count;
                    }
                }

                if (bestMultipleAction != null)
                {
                    _autoWait = AutoCooldown;
                    Execute(bestMultipleAction);
                    return;
                }

                ///////////////////////////////////////////////////////
                //
                // CONSIDER SELF ACTIONS
                //
                ///////////////////////////////////////////////////////

                for (int i = 0; i < Actions.Length; i++)
                {
                    var action = Actions[i];
                    if (action.Wait > float.Epsilon || !action.Auto || !action.NeedsOnlySelf)
                    {
                        continue;
                    }

                    if (action.CanTargetSelf && action.IsNeededFor(_actor))
                    {
                        if (_actor == Priority)
                        {
                            _autoWait = AutoCooldown;
                            Execute(action, _actor);
                            return;
                        }

                        bestSingleAction       = action;
                        bestSingleActionTarget = _actor;
                        break;
                    }
                }

                ///////////////////////////////////////////////////////
                //
                // CONSIDER SINGLE TARGET ACTIONS
                //
                ///////////////////////////////////////////////////////

                for (int i = 0; i < Actions.Length; i++)
                {
                    var action = Actions[i];
                    if (action.Wait > float.Epsilon || !action.Auto || !action.NeedsSingleTargetActor)
                    {
                        continue;
                    }

                    Actor best         = null;
                    var   bestDistance = 0f;
                    var   isBestSelf   = false;

                    for (int j = 0; j < _nearbyActors.Count; j++)
                    {
                        var actor = _nearbyActors[j];

                        if (!actor.IsAlive && action.ShouldIgnoreDead)
                        {
                            continue;
                        }

                        if (actor == _actor)
                        {
                            if (action.CanTargetSelf && action.IsNeededFor(actor))
                            {
                                if (actor == Priority)
                                {
                                    _autoWait = AutoCooldown;
                                    Execute(action, actor);
                                    return;
                                }

                                if (best == null)
                                {
                                    best         = actor;
                                    bestDistance = 0;
                                    isBestSelf   = true;
                                }
                            }
                        }
                        else if (actor.Side == _actor.Side)
                        {
                            if (action.CanTargetAlly && action.IsNeededFor(actor))
                            {
                                if (actor == Priority)
                                {
                                    _autoWait = AutoCooldown;
                                    Execute(action, actor);
                                    return;
                                }

                                var distance = Vector3.Distance(transform.position, actor.transform.position);

                                if (best == null || isBestSelf || distance < bestDistance)
                                {
                                    best         = actor;
                                    bestDistance = distance;
                                    isBestSelf   = false;
                                }
                            }
                        }
                        else if (canUseAttackAction && action.CanTargetEnemy && action.IsNeededFor(actor) && (!AutoAttackOnlyFromCover || !action.WillMoveForActor(actor)))
                        {
                            if (actor == Priority)
                            {
                                _autoWait = AutoCooldown;
                                Execute(action, actor);
                                return;
                            }

                            var distance = Vector3.Distance(transform.position, actor.transform.position);

                            if (best == null || isBestSelf || distance < bestDistance)
                            {
                                best         = actor;
                                bestDistance = distance;
                                isBestSelf   = false;
                            }
                        }
                    }

                    if (best != null)
                    {
                        bestSingleAction       = action;
                        bestSingleActionTarget = best;
                        break;
                    }
                }

                ///////////////////////////////////////////////////////
                //
                // CONSIDER AREA ACTIONS
                //
                ///////////////////////////////////////////////////////

                for (int i = 0; i < Actions.Length; i++)
                {
                    var action = Actions[i];
                    if (action.Wait > float.Epsilon || !action.Auto || !action.NeedsTargetLocation)
                    {
                        continue;
                    }

                    _possibleActionTargets.Clear();

                    for (int j = 0; j < _nearbyActors.Count; j++)
                    {
                        var actor = _nearbyActors[j];

                        if (!actor.IsAlive && action.ShouldIgnoreDead)
                        {
                            continue;
                        }

                        if (actor == _actor)
                        {
                            if (action.CanTargetSelf && action.IsNeededFor(actor))
                            {
                                _possibleActionTargets.Add(actor);
                            }
                        }
                        else if (actor.Side == _actor.Side)
                        {
                            if (action.CanTargetAlly && action.IsNeededFor(actor))
                            {
                                _possibleActionTargets.Add(actor);
                            }
                        }
                        else if (canUseAttackAction && action.CanTargetEnemy && action.IsNeededFor(actor))
                        {
                            _possibleActionTargets.Add(actor);
                        }
                    }

                    if (_possibleActionTargets.Count == 0 || (_possibleActionTargets.Count == 1 && bestSingleAction != null))
                    {
                        continue;
                    }

                    if (action.UIRadius > float.Epsilon)
                    {
                        var radius = action.UIRadius;
                        var steps  = (int)(2 * AutoDistance / radius);

                        var hasBest         = false;
                        var bestPosition    = Vector3.zero;
                        var bestDistance    = 0f;
                        var bestActorCount  = 0;
                        var bestHasPriority = false;

                        for (int x = -steps / 2; x < steps / 2; x++)
                        {
                            for (int y = -steps / 2; y < steps / 2; y++)
                            {
                                var position = transform.position + new Vector3(x * action.UIRadius, 0, y * radius);
                                var distance = Vector3.Distance(position, transform.position);

                                if (distance > AutoDistance)
                                {
                                    continue;
                                }

                                if (AutoAttackOnlyFromCover && action.CanTargetEnemy && action.WillMoveForPosition(position))
                                {
                                    continue;
                                }

                                var actorCount  = 0;
                                var hasPriority = false;

                                for (int j = 0; j < _possibleActionTargets.Count; j++)
                                {
                                    var a = _possibleActionTargets[j];

                                    if (Vector3.Distance(position, a.transform.position) < radius)
                                    {
                                        actorCount++;

                                        if (a == Priority)
                                        {
                                            hasPriority = true;
                                        }
                                    }
                                }

                                if (actorCount > 0)
                                {
                                    var isBetter = false;

                                    if (!hasBest)
                                    {
                                        isBetter = true;
                                    }
                                    else if (hasPriority && !bestHasPriority)
                                    {
                                        isBetter = false;
                                    }
                                    else if (!bestHasPriority)
                                    {
                                        if (actorCount > bestActorCount)
                                        {
                                            isBetter = true;
                                        }
                                        else if (actorCount == bestActorCount)
                                        {
                                            isBetter = distance < bestDistance;
                                        }
                                    }

                                    if (isBetter)
                                    {
                                        hasBest         = true;
                                        bestPosition    = position;
                                        bestDistance    = distance;
                                        bestHasPriority = hasPriority;
                                        bestActorCount  = actorCount;
                                    }
                                }
                            }
                        }

                        if (hasBest &&
                            (bestSingleAction == null || bestActorCount > 1))
                        {
                            _autoWait = AutoCooldown;
                            Execute(action, bestPosition);
                            return;
                        }
                    }
                }

                ///////////////////////////////////////////////////////
                //
                // EXECUTE BEST SINGLE IF NO AREA POSSIBLE
                //
                ///////////////////////////////////////////////////////

                if (bestSingleAction != null)
                {
                    _autoWait = AutoCooldown;
                    Execute(bestSingleAction, bestSingleActionTarget);
                }

                ///////////////////////////////////////////////////////
                //
                // CONSIDER NON-TARGET ACTIONS
                //
                ///////////////////////////////////////////////////////

                for (int i = 0; i < Actions.Length; i++)
                {
                    var action = Actions[i];
                    if (action.Wait > float.Epsilon || !action.Auto || action.CanTargetAny || action.CanTargetGround || action.UIRadius > float.Epsilon || action.CanTargetMultiple || action.NeedsOnlySelf)
                    {
                        continue;
                    }

                    _autoWait = AutoCooldown;
                    Execute(action);
                    return;
                }
            }
        }
Ejemplo n.º 7
0
 private void end()
 {
     Message("ToExitProcessAndMaintainPosition");
     _active.Stop();
     _active = null;
 }
Ejemplo n.º 8
0
 private void begin(AIAction command)
 {
     _actionStart = Time.timeSinceLevelLoad;
     _active      = command;
     Message("ToEnterProcess", false);
 }