示例#1
0
        public void EnterState(ActorAiState newState)
        {
            if (LockAiState)
            {
                return;
            }

            LastAiState = CurrentAiState;

            ExitState(CurrentAiState); //good place or no?

            TimeInState = 0;

            switch (newState)
            {
            case ActorAiState.Idle:
                Target = null;
                AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Idle);
                MovementComponent.AbortMove();
                break;

            case ActorAiState.Dead:
                if (CurrentAiState == ActorAiState.Dead)     //fix for glitchy looking behaviour
                {
                    break;
                }

                MovementComponent.AbortMove();
                MovementComponent.HandleDeath();
                if (DieImmediately)
                {
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Dead);
                }
                else
                {
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Dying);
                }

                AudioComponent.Ref()?.StopLivingSounds();
                AudioComponent.Ref()?.PlayDeathSound();

                if (InteractionComponent != null)
                {
                    InteractionComponent.InteractionDisabledByHit = false;
                }

                if (DestroyOnDeath)
                {
                    this.gameObject.SetActive(false);     //actually destroying the object breaks saving
                }
                if (OnDeathSpecial != null)
                {
                    OnDeathSpecial.Execute(new ActionInvokerData {
                        Activator = this
                    });
                }

                if (Target != null && Target.GetComponent <PlayerController>() && GrantXpOnDeath > 0)    //what the f**k
                {
                    GameState.Instance.PlayerRpgState.GrantXPScaled(GrantXpOnDeath);
                }
                break;

            case ActorAiState.Wandering:
                Target = null;
                AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Walking);
                //set initial destination
                Vector2 newpos = VectorUtils.GetRandomVector2(InitialPosition.GetFlatVector(), WanderRadius);
                MovementComponent.SetDestination(newpos.GetSpaceVector());
                AudioComponent.Ref()?.StartWalkSound();
                break;

            case ActorAiState.Chasing:
                if (RunOnChase)
                {
                    MovementComponent.IsRunning = true;
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Running);
                    AudioComponent.Ref()?.StartRunSound();
                }
                else
                {
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Walking);
                    AudioComponent.Ref()?.StartWalkSound();
                }

                {
                    //set target

                    if (Target == null)
                    {
                        GetSwizzledTarget();     //fix for loading saves
                    }
                    var d = Target.position;     //FIXME what if Target is null?
                    MovementComponent.SetDestination(d);
                }
                break;

            case ActorAiState.ScriptedMoveTo:
                if (RunOnChase)
                {
                    MovementComponent.IsRunning = true;
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Running);
                    AudioComponent.Ref()?.StartRunSound();
                }
                else
                {
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Walking);
                    AudioComponent.Ref()?.StartWalkSound();
                }
                MovementComponent.SetDestination(MovementComponent.MovementTarget);
                break;

            case ActorAiState.Attacking:
                if (AttackComponent == null)
                {
                    Debug.LogError($"{name} tried to attack, but has no attack component!");
                    EnterState(ActorAiState.Idle);
                    return;
                }

                if (Target == null)
                {
                    GetSwizzledTarget();     //fix for loading saves
                }
                //set animation, fire projectile, set timer
                AttackComponent.BeginAttack();
                break;

            case ActorAiState.Covering:
                break;

            case ActorAiState.Hurting:
                AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Hurting);
                AudioComponent.Ref()?.PlayPainSound();
                break;

            case ActorAiState.Fleeing:
                if (RunOnFlee)
                {
                    MovementComponent.IsRunning = true;
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Running);
                    AudioComponent.Ref()?.StartRunSound();
                }
                else
                {
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Walking);
                    AudioComponent.Ref()?.StartWalkSound();
                }

                {
                    //set target
                    var d = transform.position + ((Target.position - transform.position).normalized * -(1 + Mathf.Abs(MovementComponent.TargetThreshold)));
                    MovementComponent.SetDestination(d);
                }
                break;

            default:
                break;
            }

            CurrentAiState = newState;
        }
示例#2
0
        private void UpdateState()
        {
            //forced death check
            if (CurrentAiState != ActorAiState.Dead)
            {
                if (Health <= 0)
                {
                    EnterState(ActorAiState.Dead);
                }
            }

            //hack to retrieve swizzled target after a load
            GetSwizzledTarget();

            switch (CurrentAiState)
            {
            case ActorAiState.Idle:
                if (Aggressive)
                {
                    //search for targets, select target
                    SelectTarget();
                    if (Target != null)
                    {
                        EnterState(ActorAiState.Chasing);
                    }
                }
                break;

            case ActorAiState.Wandering:
                //TODO aggression
                if (MovementComponent.DistToTarget <= WanderThreshold || TimeInState >= WanderTimeout)
                {
                    Vector2 newpos = VectorUtils.GetRandomVector2(InitialPosition.GetFlatVector(), WanderRadius);
                    MovementComponent.SetDestination(newpos.GetSpaceVector());
                    TimeInState = 0;
                }
                if (Aggressive)
                {
                    //search for targets, select target
                    SelectTarget();
                    if (Target != null)
                    {
                        EnterState(ActorAiState.Chasing);
                        AudioComponent.Ref()?.PlayAlertSound();
                    }
                }
                break;

            case ActorAiState.Chasing:
                if (!RpgWorldUtils.TargetIsAlive(Target))
                {
                    EnterState(BaseAiState);
                    break;
                }

                if ((MetaState.Instance.SessionFlags.Contains("NoTarget") || GameState.Instance.PlayerFlags.Contains(PlayerFlags.NoTarget)) && Target.GetComponent <PlayerController>())
                {
                    EnterState(BaseAiState);
                    break;
                }

                if (AttackComponent != null && AttackComponent.ReadyToAttack && AttackComponent.TargetInRange)
                {
                    EnterState(ActorAiState.Attacking);
                    return;
                }
                else
                {
                    //set target
                    var d = Target.position;
                    MovementComponent.SetDestination(d);
                }
                if (!Relentless)
                {
                    //break off if we are too far away or too badly hurt
                    if (Health <= (MaxHealth * 0.2f))
                    {
                        EnterState(ActorAiState.Fleeing);
                    }
                    else if ((Target.position - transform.position).magnitude > SearchRadius)
                    {
                        EnterState(BaseAiState);
                        Target = null;
                    }
                }
                break;

            case ActorAiState.ScriptedMoveTo:
                if (MovementComponent.AtTarget)     //we made it!
                {
                    EnterState(ActorAiState.Idle);  //don't wander off if you were sent there!
                }
                break;

            case ActorAiState.Attacking:
                //wait...
                if (!AttackComponent.DidAttack && AttackComponent.WarmupIsDone)
                {
                    AttackComponent.DoAttack();     //waaaaay too complicated to cram here
                }
                if (AttackComponent.AttackIsDone)
                {
                    //just return
                    if (!RpgWorldUtils.TargetIsAlive(Target))
                    {
                        EnterState(BaseAiState);
                    }
                    else
                    {
                        EnterState(ActorAiState.Chasing);
                    }
                }
                break;

            case ActorAiState.Hurting:
                if (TimeInState >= PainWaitTime)
                {
                    if (BeenHit && Target != null)
                    {
                        EnterState(ActorAiState.Chasing);
                    }
                    else
                    {
                        EnterState(LastAiState);
                    }
                }
                break;

            case ActorAiState.Fleeing:
                //stop running if far enough away, or target is gone
                if (!RpgWorldUtils.TargetIsAlive(Target) || (Target.position - transform.position).magnitude > SearchRadius)
                {
                    EnterState(BaseAiState);
                    Target = null;
                    break;
                }
                {
                    //set target
                    var d = transform.position + ((Target.position - transform.position).normalized * -(1 + Mathf.Abs(MovementComponent.TargetThreshold)));
                    MovementComponent.SetDestination(d);
                }
                break;
            }
        }
示例#3
0
        public void EnterState(ActorAiState newState)
        {
            if (LockAiState)
            {
                return;
            }

            if (newState != CurrentAiState)
            {
                LastAiState = CurrentAiState;
            }

            ExitState(CurrentAiState); //good place or no?

            TimeInState = 0;

            switch (newState)
            {
            case ActorAiState.Idle:
                Target = null;
                AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Idle);
                MovementComponent.AbortMove();
                break;

            case ActorAiState.Dead:
            {
                if (CurrentAiState == ActorAiState.Dead)         //fix for glitchy looking behaviour
                {
                    break;
                }

                MovementComponent.AbortMove();
                MovementComponent.HandleDeath();
                var deathStateArgs = new DeathStateActorAnimationArgs()
                {
                    DamageEffector = LastHit?.DamageEffector ?? 0, DamageType = LastHit?.DamageType ?? 0, ExtremeDeath = WasExtremeDeath, HitLocation = LastHit?.HitLocation ?? 0, HitMaterial = LastHit?.HitMaterial ?? 0
                };
                if (DieImmediately)
                {
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Dead, deathStateArgs);
                }
                else
                {
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Dying, deathStateArgs);
                }

                AudioComponent.Ref()?.StopLivingSounds();
                if (WasExtremeDeath)
                {
                    AudioComponent.Ref()?.PlayExtremeDeathSound();
                }
                else
                {
                    AudioComponent.Ref()?.PlayDeathSound();
                }

                if (InteractionComponent != null)
                {
                    InteractionComponent.InteractionDisabledByHit = false;
                }

                if (DestroyOnDeath)
                {
                    this.gameObject.SetActive(false);         //actually destroying the object breaks saving
                }
                if (OnDeathSpecial != null)
                {
                    OnDeathSpecial.Execute(new ActionInvokerData {
                            Activator = this
                        });
                }

                if (DisableHitboxesOnDeath)
                {
                    var hitboxComponents = GetComponentsInChildren <IHitboxComponent>(true);
                    foreach (var hitboxComponent in hitboxComponents)
                    {
                        if (hitboxComponent is MonoBehaviour mb)         //IHitboxComponent does not actually imply MonoBehaviour
                        {
                            mb.gameObject.SetActive(false);
                        }
                    }
                }

                if (DisableCollidersOnDeath)
                {
                    var colliders = GetComponentsInChildren <Collider>(true);
                    foreach (var collider in colliders)
                    {
                        collider.enabled = false;
                    }
                }

                if (
                    ((LastHit != null && LastHit.Value.Originator != null && LastHit.Value.Originator is PlayerController) ||
                     (Target != null && Target.GetComponent <PlayerController>())
                    ) &&
                    GrantXpOnDeath > 0
                    )
                {
                    GameState.Instance.PlayerRpgState.GrantXPScaled(GrantXpOnDeath);
                }
            }
            break;

            case ActorAiState.Wandering:
                Target = null;
                AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Walking);
                //set initial destination
                Vector2 newpos = VectorUtils.GetRandomVector2(InitialPosition.GetFlatVector(), WanderRadius);
                MovementComponent.SetDestination(newpos.GetSpaceVector());
                AudioComponent.Ref()?.StartWalkSound();
                break;

            case ActorAiState.Chasing:
                if (RunOnChase)
                {
                    MovementComponent.IsRunning = true;
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Running);
                    AudioComponent.Ref()?.StartRunSound();
                }
                else
                {
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Walking);
                    AudioComponent.Ref()?.StartWalkSound();
                }

                {
                    //set target

                    if (Target == null)
                    {
                        GetSwizzledTarget();     //fix for loading saves
                    }
                    SetChaseDestination();
                }
                break;

            case ActorAiState.ScriptedMoveTo:
                if (RunOnChase)
                {
                    MovementComponent.IsRunning = true;
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Running);
                    AudioComponent.Ref()?.StartRunSound();
                }
                else
                {
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Walking);
                    AudioComponent.Ref()?.StartWalkSound();
                }
                MovementComponent.SetDestination(MovementComponent.MovementTarget);
                break;

            case ActorAiState.Attacking:
                if (AttackComponent == null)
                {
                    Debug.LogError($"{name} tried to attack, but has no attack component!");
                    EnterState(ActorAiState.Idle);
                    return;
                }

                if (Target == null)
                {
                    GetSwizzledTarget();     //fix for loading saves
                }
                //set animation, fire projectile, set timer
                AttackComponent.BeginAttack();
                break;

            case ActorAiState.Covering:
                break;

            case ActorAiState.Hurting:
                AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Hurting);
                AudioComponent.Ref()?.PlayPainSound();
                break;

            case ActorAiState.Fleeing:
                if (RunOnFlee)
                {
                    MovementComponent.IsRunning = true;
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Running);
                    AudioComponent.Ref()?.StartRunSound();
                }
                else
                {
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Walking);
                    AudioComponent.Ref()?.StartWalkSound();
                }

                {
                    //set target
                    var d = transform.position + ((Target.position - transform.position).normalized * -(1 + Mathf.Abs(MovementComponent.TargetThreshold)));
                    MovementComponent.SetDestination(d);
                }
                break;

            case ActorAiState.ScriptedAction:
                //nop
                break;

            default:
                break;
            }

            CurrentAiState = newState;
        }